Linux-PM Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v5 00/18] add thermal driver for h6
@ 2019-08-10  5:28 Yangtao Li
  2019-08-10  5:28 ` [PATCH v5 01/18] thermal: sun8i: " Yangtao Li
                   ` (19 more replies)
  0 siblings, 20 replies; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

This patchset add support for A64, H3, H5, H6 and R40 thermal sensor.

Thx to Icenowy and Vasily.

BTY, do a cleanup in thermal makfile.

Icenowy Zheng (3):
  thermal: sun8i: allow to use custom temperature calculation function
  thermal: sun8i: add support for Allwinner H5 thermal sensor
  thermal: sun8i: add support for Allwinner R40 thermal sensor

Vasily Khoruzhick (1):
  thermal: sun8i: add thermal driver for A64

Yangtao Li (14):
  thermal: sun8i: add thermal driver for h6
  dt-bindings: thermal: add binding document for h6 thermal controller
  thermal: fix indentation in makefile
  thermal: sun8i: get ths sensor number from device compatible
  thermal: sun8i: rework for sun8i_ths_get_temp()
  thermal: sun8i: get ths init func from device compatible
  thermal: sun8i: rework for ths irq handler func
  thermal: sun8i: support mod clocks
  thermal: sun8i: rework for ths calibrate func
  dt-bindings: thermal: add binding document for h3 thermal controller
  thermal: sun8i: add thermal driver for h3
  dt-bindings: thermal: add binding document for a64 thermal controller
  dt-bindings: thermal: add binding document for h5 thermal controller
  dt-bindings: thermal: add binding document for r40 thermal controller

 .../bindings/thermal/sun8i-thermal.yaml       | 157 +++++
 MAINTAINERS                                   |   7 +
 drivers/thermal/Kconfig                       |  14 +
 drivers/thermal/Makefile                      |   9 +-
 drivers/thermal/sun8i_thermal.c               | 596 ++++++++++++++++++
 5 files changed, 779 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
 create mode 100644 drivers/thermal/sun8i_thermal.c

---
v5:
-add more support
-some trival fix
---
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 01/18] thermal: sun8i: add thermal driver for h6
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
@ 2019-08-10  5:28 ` " Yangtao Li
  2019-09-01  2:06   ` Ondřej Jirman
  2019-09-01 21:04   ` Ondřej Jirman
  2019-08-10  5:28 ` [PATCH v5 02/18] dt-bindings: thermal: add binding document for h6 thermal controller Yangtao Li
                   ` (18 subsequent siblings)
  19 siblings, 2 replies; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

This patch adds the support for allwinner thermal sensor, within
allwinner SoC. It will register sensors for thermal framework
and use device tree to bind cooling device.

Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
---
 MAINTAINERS                     |   7 +
 drivers/thermal/Kconfig         |  14 ++
 drivers/thermal/Makefile        |   1 +
 drivers/thermal/sun8i_thermal.c | 399 ++++++++++++++++++++++++++++++++
 4 files changed, 421 insertions(+)
 create mode 100644 drivers/thermal/sun8i_thermal.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 47800d32cfbc..89dc43f4064d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -682,6 +682,13 @@ L:	linux-crypto@vger.kernel.org
 S:	Maintained
 F:	drivers/crypto/sunxi-ss/
 
+ALLWINNER THERMAL DRIVER
+M:	Yangtao Li <tiny.windzz@gmail.com>
+L:	linux-pm@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
+F:	drivers/thermal/sun8i_thermal.c
+
 ALLWINNER VPU DRIVER
 M:	Maxime Ripard <maxime.ripard@bootlin.com>
 M:	Paul Kocialkowski <paul.kocialkowski@bootlin.com>
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 9966364a6deb..f8b73b32b92d 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -262,6 +262,20 @@ config SPEAR_THERMAL
 	  Enable this to plug the SPEAr thermal sensor driver into the Linux
 	  thermal framework.
 
+config SUN8I_THERMAL
+	tristate "Allwinner sun8i thermal driver"
+	depends on ARCH_SUNXI || COMPILE_TEST
+	depends on HAS_IOMEM
+	depends on NVMEM
+	depends on OF
+	depends on RESET_CONTROLLER
+	help
+	  Support for the sun8i thermal sensor driver into the Linux thermal
+	  framework.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called sun8i-thermal.
+
 config ROCKCHIP_THERMAL
 	tristate "Rockchip thermal driver"
 	depends on ARCH_ROCKCHIP || COMPILE_TEST
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 74a37c7f847a..fa6f8b206281 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -31,6 +31,7 @@ thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
 obj-y				+= broadcom/
 obj-$(CONFIG_THERMAL_MMIO)		+= thermal_mmio.o
 obj-$(CONFIG_SPEAR_THERMAL)	+= spear_thermal.o
+obj-$(CONFIG_SUN8I_THERMAL)     += sun8i_thermal.o
 obj-$(CONFIG_ROCKCHIP_THERMAL)	+= rockchip_thermal.o
 obj-$(CONFIG_RCAR_THERMAL)	+= rcar_thermal.o
 obj-$(CONFIG_RCAR_GEN3_THERMAL)	+= rcar_gen3_thermal.o
diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
new file mode 100644
index 000000000000..2ce36fa3fec3
--- /dev/null
+++ b/drivers/thermal/sun8i_thermal.c
@@ -0,0 +1,399 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Thermal sensor driver for Allwinner SOC
+ * Copyright (C) 2019 Yangtao Li
+ *
+ * Based on the work of Icenowy Zheng <icenowy@aosc.io>
+ * Based on the work of Ondrej Jirman <megous@megous.com>
+ * Based on the work of Josef Gajdusek <atx@atx.name>
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/thermal.h>
+
+#define MAX_SENSOR_NUM	4
+
+#define SUN50I_H6_SENSOR_NUM	2
+#define SUN50I_H6_OFFSET	-2794
+#define SUN50I_H6_SCALE		-67
+
+#define FT_TEMP_MASK				GENMASK(11, 0)
+#define TEMP_CALIB_MASK				GENMASK(11, 0)
+#define TEMP_TO_REG				672
+#define CALIBRATE_DEFAULT			0x800
+
+#define SUN50I_THS_CTRL0			0x00
+#define SUN50I_H6_THS_ENABLE			0x04
+#define SUN50I_H6_THS_PC			0x08
+#define SUN50I_H6_THS_DIC			0x10
+#define SUN50I_H6_THS_DIS			0x20
+#define SUN50I_H6_THS_MFC			0x30
+#define SUN50I_H6_THS_TEMP_CALIB		0xa0
+#define SUN50I_H6_THS_TEMP_DATA			0xc0
+
+#define SUN50I_THS_CTRL0_T_ACQ(x)		((GENMASK(15, 0) & (x)) << 16)
+#define SUN50I_THS_FILTER_EN			BIT(2)
+#define SUN50I_THS_FILTER_TYPE(x)		(GENMASK(1, 0) & (x))
+#define SUN50I_H6_THS_PC_TEMP_PERIOD(x)		((GENMASK(19, 0) & (x)) << 12)
+#define SUN50I_H6_THS_DATA_IRQ_STS(x)		BIT(x)
+
+/* millidegree celsius */
+#define SUN50I_H6_FT_DEVIATION			7000
+
+struct ths_device;
+
+struct tsensor {
+	struct ths_device		*tmdev;
+	struct thermal_zone_device	*tzd;
+	int				id;
+};
+
+struct ths_device {
+	struct device				*dev;
+	struct regmap				*regmap;
+	struct reset_control			*reset;
+	struct clk				*bus_clk;
+	struct tsensor				sensor[MAX_SENSOR_NUM];
+};
+
+/* Temp Unit: millidegree Celsius */
+static int sun8i_ths_reg2temp(struct ths_device *tmdev,
+			      int reg)
+{
+	return (reg + SUN50I_H6_OFFSET) * SUN50I_H6_SCALE;
+}
+
+static int sun8i_ths_get_temp(void *data, int *temp)
+{
+	struct tsensor *s = data;
+	struct ths_device *tmdev = s->tmdev;
+	int val;
+
+	regmap_read(tmdev->regmap, SUN50I_H6_THS_TEMP_DATA +
+		    0x4 * s->id, &val);
+
+	/* ths have no data yet */
+	if (!val)
+		return -EAGAIN;
+
+	*temp = sun8i_ths_reg2temp(tmdev, val);
+	/*
+	 * XX - According to the original sdk, there are some platforms(rarely)
+	 * that add a fixed offset value after calculating the temperature
+	 * value. We can't simply put it on the formula for calculating the
+	 * temperature above, because the formula for calculating the
+	 * temperature above is also used when the sensor is calibrated. If
+	 * do this, the correct calibration formula is hard to know.
+	 */
+	*temp += SUN50I_H6_FT_DEVIATION;
+
+	return 0;
+}
+
+static const struct thermal_zone_of_device_ops ths_ops = {
+	.get_temp = sun8i_ths_get_temp,
+};
+
+static const struct regmap_config config = {
+	.reg_bits = 32,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.fast_io = true,
+};
+
+static irqreturn_t sun50i_h6_irq_thread(int irq, void *data)
+{
+	struct ths_device *tmdev = data;
+	int i, state;
+
+	regmap_read(tmdev->regmap, SUN50I_H6_THS_DIS, &state);
+
+	for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
+
+		if (state & SUN50I_H6_THS_DATA_IRQ_STS(i)) {
+			/* clear data irq pending */
+			regmap_write(tmdev->regmap, SUN50I_H6_THS_DIS,
+				     SUN50I_H6_THS_DATA_IRQ_STS(i));
+
+			thermal_zone_device_update(tmdev->sensor[i].tzd,
+						   THERMAL_EVENT_UNSPECIFIED);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int sun50i_ths_calibrate(struct ths_device *tmdev)
+{
+	struct nvmem_cell *calcell;
+	struct device *dev = tmdev->dev;
+	u16 *caldata;
+	size_t callen;
+	int ft_temp;
+	int i, ret = 0;
+
+	calcell = devm_nvmem_cell_get(dev, "calib");
+	if (IS_ERR(calcell)) {
+		if (PTR_ERR(calcell) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		/*
+		 * Even if the external calibration data stored in sid is
+		 * not accessible, the THS hardware can still work, although
+		 * the data won't be so accurate.
+		 *
+		 * The default value of calibration register is 0x800 for
+		 * every sensor, and the calibration value is usually 0x7xx
+		 * or 0x8xx, so they won't be away from the default value
+		 * for a lot.
+		 *
+		 * So here we do not return error if the calibartion data is
+		 * not available, except the probe needs deferring.
+		 */
+		goto out;
+	}
+
+	caldata = nvmem_cell_read(calcell, &callen);
+	if (IS_ERR(caldata)) {
+		ret = PTR_ERR(caldata);
+		goto out;
+	}
+
+	if (!caldata[0] || callen < 2 + 2 * SUN50I_H6_SENSOR_NUM) {
+		ret = -EINVAL;
+		goto out_free;
+	}
+
+	/*
+	 * efuse layout:
+	 *
+	 *	0   11  16	 32
+	 *	+-------+-------+-------+
+	 *	|temp|  |sensor0|sensor1|
+	 *	+-------+-------+-------+
+	 *
+	 * The calibration data on the H6 is the ambient temperature and
+	 * sensor values that are filled during the factory test stage.
+	 *
+	 * The unit of stored FT temperature is 0.1 degreee celusis.
+	 * Through the stored ambient temperature and the data read
+	 * by the sensor, after a certain calculation, the calibration
+	 * value to be compensated can be obtained.
+	 */
+	ft_temp = caldata[0] & FT_TEMP_MASK;
+
+	for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
+		int reg = (int)caldata[i + 1];
+		int sensor_temp = sun8i_ths_reg2temp(tmdev, reg);
+		int delta, cdata, offset;
+
+		/*
+		 * To calculate the calibration value:
+		 *
+		 * X(in Celsius) = Ts - ft_temp
+		 * delta = X * 10000 / TEMP_TO_REG
+		 * cdata = CALIBRATE_DEFAULT - delta
+		 *
+		 * cdata: calibration value
+		 */
+		delta = (sensor_temp - ft_temp * 100) * 10 / TEMP_TO_REG;
+		cdata = CALIBRATE_DEFAULT - delta;
+		if (cdata & ~TEMP_CALIB_MASK) {
+			/*
+			 * Calibration value more than 12-bit, but calibration
+			 * register is 12-bit. In this case, ths hardware can
+			 * still work without calibration, although the data
+			 * won't be so accurate.
+			 */
+			dev_warn(dev, "sensor%d is not calibrated.\n", i);
+
+			continue;
+		}
+
+		offset = (i % 2) << 4;
+		regmap_update_bits(tmdev->regmap,
+				   SUN50I_H6_THS_TEMP_CALIB + ((i >> 1) * 4),
+				   0xfff << offset,
+				   cdata << offset);
+	}
+
+out_free:
+	kfree(caldata);
+out:
+	return ret;
+}
+
+static int sun8i_ths_resource_init(struct ths_device *tmdev)
+{
+	struct device *dev = tmdev->dev;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct resource *mem;
+	void __iomem *base;
+	int ret;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, mem);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	tmdev->regmap = devm_regmap_init_mmio(dev, base, &config);
+	if (IS_ERR(tmdev->regmap))
+		return PTR_ERR(tmdev->regmap);
+
+	tmdev->reset = devm_reset_control_get(dev, 0);
+	if (IS_ERR(tmdev->reset))
+		return PTR_ERR(tmdev->reset);
+
+	tmdev->bus_clk = devm_clk_get(&pdev->dev, "bus");
+	if (IS_ERR(tmdev->bus_clk))
+		return PTR_ERR(tmdev->bus_clk);
+
+	ret = reset_control_deassert(tmdev->reset);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(tmdev->bus_clk);
+	if (ret)
+		goto assert_reset;
+
+	ret = sun50i_ths_calibrate(tmdev);
+	if (ret)
+		goto bus_disable;
+
+	return 0;
+
+bus_disable:
+	clk_disable_unprepare(tmdev->bus_clk);
+assert_reset:
+	reset_control_assert(tmdev->reset);
+
+	return ret;
+}
+
+static int sun50i_h6_thermal_init(struct ths_device *tmdev)
+{
+	int val;
+
+	/*
+	 * clkin = 24MHz
+	 * T acquire = clkin / (x + 1)
+	 *           = 20us
+	 */
+	regmap_write(tmdev->regmap, SUN50I_THS_CTRL0,
+		     SUN50I_THS_CTRL0_T_ACQ(479));
+	/* average over 4 samples */
+	regmap_write(tmdev->regmap, SUN50I_H6_THS_MFC,
+		     SUN50I_THS_FILTER_EN |
+		     SUN50I_THS_FILTER_TYPE(1));
+	/* period = (x + 1) * 4096 / clkin; ~10ms */
+	regmap_write(tmdev->regmap, SUN50I_H6_THS_PC,
+		     SUN50I_H6_THS_PC_TEMP_PERIOD(58));
+	/* enable sensor */
+	val = GENMASK(SUN50I_H6_SENSOR_NUM - 1, 0);
+	regmap_write(tmdev->regmap, SUN50I_H6_THS_ENABLE, val);
+	/* thermal data interrupt enable */
+	val = GENMASK(SUN50I_H6_SENSOR_NUM - 1, 0);
+	regmap_write(tmdev->regmap, SUN50I_H6_THS_DIC, val);
+
+	return 0;
+}
+
+static int sun8i_ths_register(struct ths_device *tmdev)
+{
+	struct thermal_zone_device *tzd;
+	int i;
+
+	for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
+		tmdev->sensor[i].tmdev = tmdev;
+		tmdev->sensor[i].id = i;
+		tmdev->sensor[i].tzd =
+			devm_thermal_zone_of_sensor_register(tmdev->dev,
+							     i,
+							     &tmdev->sensor[i],
+							     &ths_ops);
+		if (IS_ERR(tmdev->sensor[i].tzd))
+			return PTR_ERR(tzd);
+	}
+
+	return 0;
+}
+
+static int sun8i_ths_probe(struct platform_device *pdev)
+{
+	struct ths_device *tmdev;
+	struct device *dev = &pdev->dev;
+	int ret, irq;
+
+	tmdev = devm_kzalloc(dev, sizeof(*tmdev), GFP_KERNEL);
+	if (!tmdev)
+		return -ENOMEM;
+
+	tmdev->dev = dev;
+	platform_set_drvdata(pdev, tmdev);
+
+	ret = sun8i_ths_resource_init(tmdev);
+	if (ret)
+		return ret;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	ret = sun50i_h6_thermal_init(tmdev);
+	if (ret)
+		return ret;
+
+	ret = sun8i_ths_register(tmdev);
+	if (ret)
+		return ret;
+
+	/*
+	 * Avoid entering the interrupt handler, the thermal device is not
+	 * registered yet, we deffer the registration of the interrupt to
+	 * the end.
+	 */
+	ret = devm_request_threaded_irq(dev, irq, NULL,
+					sun50i_h6_irq_thread,
+					IRQF_ONESHOT, "ths", tmdev);
+	if (ret)
+		return ret;
+
+	return ret;
+}
+
+static int sun8i_ths_remove(struct platform_device *pdev)
+{
+	struct ths_device *tmdev = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(tmdev->bus_clk);
+	reset_control_assert(tmdev->reset);
+
+	return 0;
+}
+
+static const struct of_device_id of_ths_match[] = {
+	{ .compatible = "allwinner,sun50i-h6-ths"},
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, of_ths_match);
+
+static struct platform_driver ths_driver = {
+	.probe = sun8i_ths_probe,
+	.remove = sun8i_ths_remove,
+	.driver = {
+		.name = "sun8i-thermal",
+		.of_match_table = of_ths_match,
+	},
+};
+module_platform_driver(ths_driver);
+
+MODULE_DESCRIPTION("Thermal sensor driver for Allwinner SOC");
+MODULE_LICENSE("GPL v2");
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 02/18] dt-bindings: thermal: add binding document for h6 thermal controller
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
  2019-08-10  5:28 ` [PATCH v5 01/18] thermal: sun8i: " Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-12  8:56   ` Maxime Ripard
  2019-08-10  5:28 ` [PATCH v5 03/18] thermal: fix indentation in makefile Yangtao Li
                   ` (17 subsequent siblings)
  19 siblings, 1 reply; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

This patch adds binding document for allwinner h6 thermal controller.

Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
---
 .../bindings/thermal/sun8i-thermal.yaml       | 79 +++++++++++++++++++
 1 file changed, 79 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml

diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
new file mode 100644
index 000000000000..e0973199ba3c
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/thermal/sun8i-thermal.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner SUN8I Thermal Controller Device Tree Bindings
+
+maintainers:
+  - Yangtao Li <tiny.windzz@gmail.com>
+
+description: |-
+  This describes the device tree binding for the Allwinner thermal
+  controller which measures the on-SoC temperatures.
+
+properties:
+  compatible:
+    enum:
+      - allwinner,sun50i-h6-ths
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    const: bus
+
+  "#thermal-sensor-cells":
+    const: 1
+
+  nvmem-cells:
+    description: ths calibrate data
+
+  nvmem-cell-names:
+    const: calib
+
+required:
+  - compatible
+  - reg
+  - reset
+  - clocks
+  - clock-names
+  - interrupts
+  - "#thermal-sensor-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    ths: ths@5070400 {
+        compatible = "allwinner,sun50i-h6-ths";
+        reg = <0x05070400 0x100>;
+        clocks = <&ccu CLK_BUS_THS>;
+        clock-names = "bus";
+        resets = <&ccu RST_BUS_THS>;
+        interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+        nvmem-cells = <&tsen_calib>;
+        nvmem-cell-names = "calib";
+        #thermal-sensor-cells = <1>;
+    };
+
+    sid: sid@3006000 {
+        compatible = "allwinner,sun50i-h6-sid";
+        reg = <0x03006000 0x400>;
+        #address-cells = <1>;
+        #size-cells = <1>;
+        tsen_calib: calib@14 {
+                reg = <0x14 6>;
+        };
+    };
+...
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 03/18] thermal: fix indentation in makefile
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
  2019-08-10  5:28 ` [PATCH v5 01/18] thermal: sun8i: " Yangtao Li
  2019-08-10  5:28 ` [PATCH v5 02/18] dt-bindings: thermal: add binding document for h6 thermal controller Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-28 12:40   ` Zhang Rui
  2019-08-10  5:28 ` [PATCH v5 04/18] thermal: sun8i: get ths sensor number from device compatible Yangtao Li
                   ` (16 subsequent siblings)
  19 siblings, 1 reply; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

To unify code style.

Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
---
 drivers/thermal/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index fa6f8b206281..d7eafb5ef8ef 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -5,7 +5,7 @@
 
 obj-$(CONFIG_THERMAL)		+= thermal_sys.o
 thermal_sys-y			+= thermal_core.o thermal_sysfs.o \
-					thermal_helpers.o
+				   thermal_helpers.o
 
 # interface to/from other layers providing sensors
 thermal_sys-$(CONFIG_THERMAL_HWMON)		+= thermal_hwmon.o
@@ -25,11 +25,11 @@ thermal_sys-$(CONFIG_CPU_THERMAL)	+= cpu_cooling.o
 thermal_sys-$(CONFIG_CLOCK_THERMAL)	+= clock_cooling.o
 
 # devfreq cooling
-thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
+thermal_sys-$(CONFIG_DEVFREQ_THERMAL) 	+= devfreq_cooling.o
 
 # platform thermal drivers
 obj-y				+= broadcom/
-obj-$(CONFIG_THERMAL_MMIO)		+= thermal_mmio.o
+obj-$(CONFIG_THERMAL_MMIO)	+= thermal_mmio.o
 obj-$(CONFIG_SPEAR_THERMAL)	+= spear_thermal.o
 obj-$(CONFIG_SUN8I_THERMAL)     += sun8i_thermal.o
 obj-$(CONFIG_ROCKCHIP_THERMAL)	+= rockchip_thermal.o
@@ -50,7 +50,7 @@ obj-$(CONFIG_TI_SOC_THERMAL)	+= ti-soc-thermal/
 obj-y				+= st/
 obj-$(CONFIG_QCOM_TSENS)	+= qcom/
 obj-y				+= tegra/
-obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
+obj-$(CONFIG_HISI_THERMAL)     	+= hisi_thermal.o
 obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
 obj-$(CONFIG_GENERIC_ADC_THERMAL)	+= thermal-generic-adc.o
 obj-$(CONFIG_ZX2967_THERMAL)	+= zx2967_thermal.o
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 04/18] thermal: sun8i: get ths sensor number from device compatible
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (2 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 03/18] thermal: fix indentation in makefile Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-10  5:28 ` [PATCH v5 05/18] thermal: sun8i: rework for sun8i_ths_get_temp() Yangtao Li
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

For different socs, the number of ths sensors is different.
So we need to do some work in order to support more soc.

Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
---
 drivers/thermal/sun8i_thermal.c | 28 ++++++++++++++++++++--------
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 2ce36fa3fec3..e9c2acbaac74 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -22,7 +22,6 @@
 
 #define MAX_SENSOR_NUM	4
 
-#define SUN50I_H6_SENSOR_NUM	2
 #define SUN50I_H6_OFFSET	-2794
 #define SUN50I_H6_SCALE		-67
 
@@ -57,7 +56,12 @@ struct tsensor {
 	int				id;
 };
 
+struct ths_thermal_chip {
+	int		sensor_num;
+};
+
 struct ths_device {
+	const struct ths_thermal_chip		*chip;
 	struct device				*dev;
 	struct regmap				*regmap;
 	struct reset_control			*reset;
@@ -117,7 +121,7 @@ static irqreturn_t sun50i_h6_irq_thread(int irq, void *data)
 
 	regmap_read(tmdev->regmap, SUN50I_H6_THS_DIS, &state);
 
-	for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
+	for (i = 0; i < tmdev->chip->sensor_num; i++) {
 
 		if (state & SUN50I_H6_THS_DATA_IRQ_STS(i)) {
 			/* clear data irq pending */
@@ -167,7 +171,7 @@ static int sun50i_ths_calibrate(struct ths_device *tmdev)
 		goto out;
 	}
 
-	if (!caldata[0] || callen < 2 + 2 * SUN50I_H6_SENSOR_NUM) {
+	if (!caldata[0] || callen < 2 + 2 * tmdev->chip->sensor_num) {
 		ret = -EINVAL;
 		goto out_free;
 	}
@@ -190,7 +194,7 @@ static int sun50i_ths_calibrate(struct ths_device *tmdev)
 	 */
 	ft_temp = caldata[0] & FT_TEMP_MASK;
 
-	for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
+	for (i = 0; i < tmdev->chip->sensor_num; i++) {
 		int reg = (int)caldata[i + 1];
 		int sensor_temp = sun8i_ths_reg2temp(tmdev, reg);
 		int delta, cdata, offset;
@@ -297,10 +301,10 @@ static int sun50i_h6_thermal_init(struct ths_device *tmdev)
 	regmap_write(tmdev->regmap, SUN50I_H6_THS_PC,
 		     SUN50I_H6_THS_PC_TEMP_PERIOD(58));
 	/* enable sensor */
-	val = GENMASK(SUN50I_H6_SENSOR_NUM - 1, 0);
+	val = GENMASK(tmdev->chip->sensor_num - 1, 0);
 	regmap_write(tmdev->regmap, SUN50I_H6_THS_ENABLE, val);
 	/* thermal data interrupt enable */
-	val = GENMASK(SUN50I_H6_SENSOR_NUM - 1, 0);
+	val = GENMASK(tmdev->chip->sensor_num - 1, 0);
 	regmap_write(tmdev->regmap, SUN50I_H6_THS_DIC, val);
 
 	return 0;
@@ -311,7 +315,7 @@ static int sun8i_ths_register(struct ths_device *tmdev)
 	struct thermal_zone_device *tzd;
 	int i;
 
-	for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
+	for (i = 0; i < tmdev->chip->sensor_num; i++) {
 		tmdev->sensor[i].tmdev = tmdev;
 		tmdev->sensor[i].id = i;
 		tmdev->sensor[i].tzd =
@@ -337,6 +341,10 @@ static int sun8i_ths_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	tmdev->dev = dev;
+	tmdev->chip = of_device_get_match_data(&pdev->dev);
+	if (!tmdev->chip)
+		return -EINVAL;
+
 	platform_set_drvdata(pdev, tmdev);
 
 	ret = sun8i_ths_resource_init(tmdev);
@@ -379,8 +387,12 @@ static int sun8i_ths_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct ths_thermal_chip sun50i_h6_ths = {
+	.sensor_num = 2,
+};
+
 static const struct of_device_id of_ths_match[] = {
-	{ .compatible = "allwinner,sun50i-h6-ths"},
+	{ .compatible = "allwinner,sun50i-h6-ths", .data = &sun50i_h6_ths },
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, of_ths_match);
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 05/18] thermal: sun8i: rework for sun8i_ths_get_temp()
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (3 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 04/18] thermal: sun8i: get ths sensor number from device compatible Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-10  5:28 ` [PATCH v5 06/18] thermal: sun8i: get ths init func from device compatible Yangtao Li
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

For different socs, the way they get and calculate the
temperature is roughly the same. So get the difference
from device compatible.

Difference point:
  1) temperature calculation formula parameters
  2) ths data register start address

Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
---
 drivers/thermal/sun8i_thermal.c | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index e9c2acbaac74..f338fa25b98e 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -22,9 +22,6 @@
 
 #define MAX_SENSOR_NUM	4
 
-#define SUN50I_H6_OFFSET	-2794
-#define SUN50I_H6_SCALE		-67
-
 #define FT_TEMP_MASK				GENMASK(11, 0)
 #define TEMP_CALIB_MASK				GENMASK(11, 0)
 #define TEMP_TO_REG				672
@@ -58,6 +55,10 @@ struct tsensor {
 
 struct ths_thermal_chip {
 	int		sensor_num;
+	int		offset;
+	int		scale;
+	int		ft_deviation;
+	int		temp_data_base;
 };
 
 struct ths_device {
@@ -73,7 +74,7 @@ struct ths_device {
 static int sun8i_ths_reg2temp(struct ths_device *tmdev,
 			      int reg)
 {
-	return (reg + SUN50I_H6_OFFSET) * SUN50I_H6_SCALE;
+	return (reg + tmdev->chip->offset) * tmdev->chip->scale;
 }
 
 static int sun8i_ths_get_temp(void *data, int *temp)
@@ -82,7 +83,7 @@ static int sun8i_ths_get_temp(void *data, int *temp)
 	struct ths_device *tmdev = s->tmdev;
 	int val;
 
-	regmap_read(tmdev->regmap, SUN50I_H6_THS_TEMP_DATA +
+	regmap_read(tmdev->regmap, tmdev->chip->temp_data_base +
 		    0x4 * s->id, &val);
 
 	/* ths have no data yet */
@@ -98,7 +99,7 @@ static int sun8i_ths_get_temp(void *data, int *temp)
 	 * temperature above is also used when the sensor is calibrated. If
 	 * do this, the correct calibration formula is hard to know.
 	 */
-	*temp += SUN50I_H6_FT_DEVIATION;
+	*temp += tmdev->chip->ft_deviation;
 
 	return 0;
 }
@@ -389,6 +390,10 @@ static int sun8i_ths_remove(struct platform_device *pdev)
 
 static const struct ths_thermal_chip sun50i_h6_ths = {
 	.sensor_num = 2,
+	.offset = -2794,
+	.scale = -67,
+	.ft_deviation = SUN50I_H6_FT_DEVIATION,
+	.temp_data_base = SUN50I_H6_THS_TEMP_DATA,
 };
 
 static const struct of_device_id of_ths_match[] = {
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 06/18] thermal: sun8i: get ths init func from device compatible
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (4 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 05/18] thermal: sun8i: rework for sun8i_ths_get_temp() Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-10  5:28 ` [PATCH v5 07/18] thermal: sun8i: rework for ths irq handler func Yangtao Li
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

There are some differences in register initialization for
different socs. So we get different initialization functions
from device compatible.

Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
---
 drivers/thermal/sun8i_thermal.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index f338fa25b98e..ad877b54f58e 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -59,6 +59,7 @@ struct ths_thermal_chip {
 	int		scale;
 	int		ft_deviation;
 	int		temp_data_base;
+	int		(*init)(struct ths_device *tmdev);
 };
 
 struct ths_device {
@@ -356,7 +357,7 @@ static int sun8i_ths_probe(struct platform_device *pdev)
 	if (irq < 0)
 		return irq;
 
-	ret = sun50i_h6_thermal_init(tmdev);
+	ret = tmdev->chip->init(tmdev);
 	if (ret)
 		return ret;
 
@@ -394,6 +395,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
 	.scale = -67,
 	.ft_deviation = SUN50I_H6_FT_DEVIATION,
 	.temp_data_base = SUN50I_H6_THS_TEMP_DATA,
+	.init = sun50i_h6_thermal_init,
 };
 
 static const struct of_device_id of_ths_match[] = {
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 07/18] thermal: sun8i: rework for ths irq handler func
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (5 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 06/18] thermal: sun8i: get ths init func from device compatible Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-10  5:28 ` [PATCH v5 08/18] thermal: sun8i: support mod clocks Yangtao Li
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

Here, we do something to prepare for the subsequent
support of multiple platforms.

1) rename sun50i_h6_irq_thread to sun8i_irq_thread, because
   this function should be suitable for all platforms.

2) introduce irq_ack callback to mask interrupt register
   differences.

Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
---
 drivers/thermal/sun8i_thermal.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index ad877b54f58e..b934bc81eba7 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -60,6 +60,7 @@ struct ths_thermal_chip {
 	int		ft_deviation;
 	int		temp_data_base;
 	int		(*init)(struct ths_device *tmdev);
+	int             (*irq_ack)(struct ths_device *tmdev);
 };
 
 struct ths_device {
@@ -116,23 +117,34 @@ static const struct regmap_config config = {
 	.fast_io = true,
 };
 
-static irqreturn_t sun50i_h6_irq_thread(int irq, void *data)
+static int sun50i_h6_irq_ack(struct ths_device *tmdev)
 {
-	struct ths_device *tmdev = data;
-	int i, state;
+	int i, state, ret = 0;
 
 	regmap_read(tmdev->regmap, SUN50I_H6_THS_DIS, &state);
 
 	for (i = 0; i < tmdev->chip->sensor_num; i++) {
-
 		if (state & SUN50I_H6_THS_DATA_IRQ_STS(i)) {
-			/* clear data irq pending */
 			regmap_write(tmdev->regmap, SUN50I_H6_THS_DIS,
 				     SUN50I_H6_THS_DATA_IRQ_STS(i));
+			ret |= BIT(i);
+		}
+	}
+
+	return ret;
+}
 
+static irqreturn_t sun8i_irq_thread(int irq, void *data)
+{
+	struct ths_device *tmdev = data;
+	int i, state;
+
+	state = tmdev->chip->irq_ack(tmdev);
+
+	for (i = 0; i < tmdev->chip->sensor_num; i++) {
+		if (state & BIT(i))
 			thermal_zone_device_update(tmdev->sensor[i].tzd,
 						   THERMAL_EVENT_UNSPECIFIED);
-		}
 	}
 
 	return IRQ_HANDLED;
@@ -371,7 +383,7 @@ static int sun8i_ths_probe(struct platform_device *pdev)
 	 * the end.
 	 */
 	ret = devm_request_threaded_irq(dev, irq, NULL,
-					sun50i_h6_irq_thread,
+					sun8i_irq_thread,
 					IRQF_ONESHOT, "ths", tmdev);
 	if (ret)
 		return ret;
@@ -396,6 +408,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
 	.ft_deviation = SUN50I_H6_FT_DEVIATION,
 	.temp_data_base = SUN50I_H6_THS_TEMP_DATA,
 	.init = sun50i_h6_thermal_init,
+	.irq_ack = sun50i_h6_irq_ack,
 };
 
 static const struct of_device_id of_ths_match[] = {
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 08/18] thermal: sun8i: support mod clocks
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (6 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 07/18] thermal: sun8i: rework for ths irq handler func Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-10  6:16   ` Vasily Khoruzhick
  2019-08-10  5:28 ` [PATCH v5 09/18] thermal: sun8i: rework for ths calibrate func Yangtao Li
                   ` (11 subsequent siblings)
  19 siblings, 1 reply; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

H3 has extra clock, so introduce something in ths_thermal_chip/ths_device
and adds the process of the clock.

This is pre-work for supprt it.

Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
---
 drivers/thermal/sun8i_thermal.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index b934bc81eba7..6f4294c2aba7 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -54,6 +54,7 @@ struct tsensor {
 };
 
 struct ths_thermal_chip {
+	bool            has_mod_clk;
 	int		sensor_num;
 	int		offset;
 	int		scale;
@@ -69,6 +70,7 @@ struct ths_device {
 	struct regmap				*regmap;
 	struct reset_control			*reset;
 	struct clk				*bus_clk;
+	struct clk                              *mod_clk;
 	struct tsensor				sensor[MAX_SENSOR_NUM];
 };
 
@@ -274,6 +276,12 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
 	if (IS_ERR(tmdev->bus_clk))
 		return PTR_ERR(tmdev->bus_clk);
 
+	if (tmdev->chip->has_mod_clk) {
+		tmdev->mod_clk = devm_clk_get(&pdev->dev, "mod");
+		if (IS_ERR(tmdev->mod_clk))
+			return PTR_ERR(tmdev->mod_clk);
+	}
+
 	ret = reset_control_deassert(tmdev->reset);
 	if (ret)
 		return ret;
@@ -282,12 +290,18 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
 	if (ret)
 		goto assert_reset;
 
-	ret = sun50i_ths_calibrate(tmdev);
+	ret = clk_prepare_enable(tmdev->mod_clk);
 	if (ret)
 		goto bus_disable;
 
+	ret = sun50i_ths_calibrate(tmdev);
+	if (ret)
+		goto mod_disable;
+
 	return 0;
 
+mod_disable:
+	clk_disable_unprepare(tmdev->mod_clk);
 bus_disable:
 	clk_disable_unprepare(tmdev->bus_clk);
 assert_reset:
@@ -395,6 +409,7 @@ static int sun8i_ths_remove(struct platform_device *pdev)
 {
 	struct ths_device *tmdev = platform_get_drvdata(pdev);
 
+	clk_disable_unprepare(tmdev->mod_clk);
 	clk_disable_unprepare(tmdev->bus_clk);
 	reset_control_assert(tmdev->reset);
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 09/18] thermal: sun8i: rework for ths calibrate func
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (7 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 08/18] thermal: sun8i: support mod clocks Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-28 12:45   ` Zhang Rui
  2019-08-10  5:28 ` [PATCH v5 10/18] dt-bindings: thermal: add binding document for h3 thermal controller Yangtao Li
                   ` (10 subsequent siblings)
  19 siblings, 1 reply; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

Here, we do something to prepare for the subsequent
support of multiple platforms.

1) rename sun50i_ths_calibrate to sun8i_ths_calibrate, because
   this function should be suitable for all platforms now.

2) introduce calibrate callback to mask calibration method
   differences.

Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
---
 drivers/thermal/sun8i_thermal.c | 86 ++++++++++++++++++---------------
 1 file changed, 48 insertions(+), 38 deletions(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 6f4294c2aba7..47c20c4c69e7 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -60,6 +60,8 @@ struct ths_thermal_chip {
 	int		scale;
 	int		ft_deviation;
 	int		temp_data_base;
+	int		(*calibrate)(struct ths_device *tmdev,
+				     u16 *caldata, int callen);
 	int		(*init)(struct ths_device *tmdev);
 	int             (*irq_ack)(struct ths_device *tmdev);
 };
@@ -152,45 +154,14 @@ static irqreturn_t sun8i_irq_thread(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int sun50i_ths_calibrate(struct ths_device *tmdev)
+static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
+				   u16 *caldata, int callen)
 {
-	struct nvmem_cell *calcell;
 	struct device *dev = tmdev->dev;
-	u16 *caldata;
-	size_t callen;
-	int ft_temp;
-	int i, ret = 0;
-
-	calcell = devm_nvmem_cell_get(dev, "calib");
-	if (IS_ERR(calcell)) {
-		if (PTR_ERR(calcell) == -EPROBE_DEFER)
-			return -EPROBE_DEFER;
-		/*
-		 * Even if the external calibration data stored in sid is
-		 * not accessible, the THS hardware can still work, although
-		 * the data won't be so accurate.
-		 *
-		 * The default value of calibration register is 0x800 for
-		 * every sensor, and the calibration value is usually 0x7xx
-		 * or 0x8xx, so they won't be away from the default value
-		 * for a lot.
-		 *
-		 * So here we do not return error if the calibartion data is
-		 * not available, except the probe needs deferring.
-		 */
-		goto out;
-	}
+	int i, ft_temp;
 
-	caldata = nvmem_cell_read(calcell, &callen);
-	if (IS_ERR(caldata)) {
-		ret = PTR_ERR(caldata);
-		goto out;
-	}
-
-	if (!caldata[0] || callen < 2 + 2 * tmdev->chip->sensor_num) {
-		ret = -EINVAL;
-		goto out_free;
-	}
+	if (!caldata[0] || callen < 2 + 2 * tmdev->chip->sensor_num)
+		return -EINVAL;
 
 	/*
 	 * efuse layout:
@@ -245,7 +216,45 @@ static int sun50i_ths_calibrate(struct ths_device *tmdev)
 				   cdata << offset);
 	}
 
-out_free:
+	return 0;
+}
+
+static int sun8i_ths_calibrate(struct ths_device *tmdev)
+{
+	struct nvmem_cell *calcell;
+	struct device *dev = tmdev->dev;
+	u16 *caldata;
+	size_t callen;
+	int ret = 0;
+
+	calcell = devm_nvmem_cell_get(dev, "calib");
+	if (IS_ERR(calcell)) {
+		if (PTR_ERR(calcell) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		/*
+		 * Even if the external calibration data stored in sid is
+		 * not accessible, the THS hardware can still work, although
+		 * the data won't be so accurate.
+		 *
+		 * The default value of calibration register is 0x800 for
+		 * every sensor, and the calibration value is usually 0x7xx
+		 * or 0x8xx, so they won't be away from the default value
+		 * for a lot.
+		 *
+		 * So here we do not return error if the calibartion data is
+		 * not available, except the probe needs deferring.
+		 */
+		goto out;
+	}
+
+	caldata = nvmem_cell_read(calcell, &callen);
+	if (IS_ERR(caldata)) {
+		ret = PTR_ERR(caldata);
+		goto out;
+	}
+
+	tmdev->chip->calibrate(tmdev, caldata, callen);
+
 	kfree(caldata);
 out:
 	return ret;
@@ -294,7 +303,7 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
 	if (ret)
 		goto bus_disable;
 
-	ret = sun50i_ths_calibrate(tmdev);
+	ret = sun8i_ths_calibrate(tmdev);
 	if (ret)
 		goto mod_disable;
 
@@ -422,6 +431,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
 	.scale = -67,
 	.ft_deviation = SUN50I_H6_FT_DEVIATION,
 	.temp_data_base = SUN50I_H6_THS_TEMP_DATA,
+	.calibrate = sun50i_h6_ths_calibrate,
 	.init = sun50i_h6_thermal_init,
 	.irq_ack = sun50i_h6_irq_ack,
 };
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 10/18] dt-bindings: thermal: add binding document for h3 thermal controller
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (8 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 09/18] thermal: sun8i: rework for ths calibrate func Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-27 15:26   ` Rob Herring
  2019-08-10  5:28 ` [PATCH v5 11/18] thermal: sun8i: add thermal driver for h3 Yangtao Li
                   ` (9 subsequent siblings)
  19 siblings, 1 reply; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

This patch adds binding document for allwinner h3 thermal controller.

Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
---
 .../bindings/thermal/sun8i-thermal.yaml       | 81 ++++++++++++++++++-
 1 file changed, 78 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
index e0973199ba3c..6624cf6b1ce8 100644
--- a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
@@ -16,6 +16,7 @@ description: |-
 properties:
   compatible:
     enum:
+      - allwinner,sun8i-h3-ths
       - allwinner,sun50i-h6-ths
 
   reg:
@@ -28,13 +29,21 @@ properties:
     maxItems: 1
 
   clocks:
-    maxItems: 1
+    minItems: 1
+    maxItems: 2
+    items:
+      - description: ths bus clock
+      - description: ths mod clock
 
   clock-names:
-    const: bus
+    minItems: 1
+    maxItems: 2
+    items:
+      - const: bus
+      - const: mod
 
   "#thermal-sensor-cells":
-    const: 1
+    enum: [ 0, 1 ]
 
   nvmem-cells:
     description: ths calibrate data
@@ -51,9 +60,75 @@ required:
   - interrupts
   - "#thermal-sensor-cells"
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: allwinner,sun50i-h6-ths
+
+    then:
+      properties:
+        clocks:
+          minItems: 1
+          maxItems: 1
+
+        clock-names:
+          minItems: 1
+          maxItems: 1
+
+    else:
+      properties:
+        clocks:
+          minItems: 2
+          maxItems: 2
+
+        clock-names:
+          minItems: 2
+          maxItems: 2
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: allwinner,sun8i-h3-ths
+
+    then:
+      properties:
+        "#thermal-sensor-cells":
+          const: 0
+
+    else:
+      properties:
+        "#thermal-sensor-cells":
+          const: 1
+
 additionalProperties: false
 
 examples:
+  - |
+    ths: ths@1c25000 {
+        compatible = "allwinner,sun8i-h3-ths";
+        reg = <0x01c25000 0x400>;
+        clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>;
+        clock-names = "bus", "mod";
+        resets = <&ccu RST_BUS_THS>;
+        interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+        nvmem-cells = <&tsen_calib>;
+        nvmem-cell-names = "calib";
+        #thermal-sensor-cells = <0>;
+    };
+
+    sid: sid@1c14000 {
+        compatible = "allwinner,sun8i-h3-sid";
+        reg = <0x1c14000 0x400>;
+        #address-cells = <1>;
+        #size-cells = <1>;
+        tsen_calib: calib@34 {
+                reg = <0x34 2>;
+        };
+    };
+
   - |
     ths: ths@5070400 {
         compatible = "allwinner,sun50i-h6-ths";
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 11/18] thermal: sun8i: add thermal driver for h3
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (9 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 10/18] dt-bindings: thermal: add binding document for h3 thermal controller Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-10  5:28 ` [PATCH v5 12/18] dt-bindings: thermal: add binding document for a64 thermal controller Yangtao Li
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

This patch adds the support for allwinner h3 thermal sensor.

Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
---
 drivers/thermal/sun8i_thermal.c | 91 +++++++++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 47c20c4c69e7..41ce8cdc0546 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -27,6 +27,14 @@
 #define TEMP_TO_REG				672
 #define CALIBRATE_DEFAULT			0x800
 
+#define SUN8I_THS_CTRL0				0x00
+#define SUN8I_THS_CTRL2				0x40
+#define SUN8I_THS_IC				0x44
+#define SUN8I_THS_IS				0x48
+#define SUN8I_THS_MFC				0x70
+#define SUN8I_THS_TEMP_CALIB			0x74
+#define SUN8I_THS_TEMP_DATA			0x80
+
 #define SUN50I_THS_CTRL0			0x00
 #define SUN50I_H6_THS_ENABLE			0x04
 #define SUN50I_H6_THS_PC			0x08
@@ -36,6 +44,10 @@
 #define SUN50I_H6_THS_TEMP_CALIB		0xa0
 #define SUN50I_H6_THS_TEMP_DATA			0xc0
 
+#define SUN8I_THS_CTRL0_T_ACQ0(x)		(GENMASK(15, 0) & (x))
+#define SUN8I_THS_CTRL2_T_ACQ1(x)		((GENMASK(15, 0) & (x)) << 16)
+#define SUN8I_THS_DATA_IRQ_STS(x)		BIT(x + 8)
+
 #define SUN50I_THS_CTRL0_T_ACQ(x)		((GENMASK(15, 0) & (x)) << 16)
 #define SUN50I_THS_FILTER_EN			BIT(2)
 #define SUN50I_THS_FILTER_TYPE(x)		(GENMASK(1, 0) & (x))
@@ -121,6 +133,23 @@ static const struct regmap_config config = {
 	.fast_io = true,
 };
 
+static int sun8i_h3_irq_ack(struct ths_device *tmdev)
+{
+	int i, state, ret = 0;
+
+	regmap_read(tmdev->regmap, SUN8I_THS_IS, &state);
+
+	for (i = 0; i < tmdev->chip->sensor_num; i++) {
+		if (state & SUN8I_THS_DATA_IRQ_STS(i)) {
+			regmap_write(tmdev->regmap, SUN8I_THS_IS,
+				     SUN8I_THS_DATA_IRQ_STS(i));
+			ret |= BIT(i);
+		}
+	}
+
+	return ret;
+}
+
 static int sun50i_h6_irq_ack(struct ths_device *tmdev)
 {
 	int i, state, ret = 0;
@@ -154,6 +183,26 @@ static irqreturn_t sun8i_irq_thread(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
+static int sun8i_h3_ths_calibrate(struct ths_device *tmdev,
+				  u16 *caldata, int callen)
+{
+	int i;
+
+	if (!caldata[0] || callen < 2 * tmdev->chip->sensor_num)
+		return -EINVAL;
+
+	for (i = 0; i < tmdev->chip->sensor_num; i++) {
+		int offset = (i % 2) << 4;
+
+		regmap_update_bits(tmdev->regmap,
+				   SUN8I_THS_TEMP_CALIB + (4 * (i >> 1)),
+				   0xfff << offset,
+				   caldata[i] << offset);
+	}
+
+	return 0;
+}
+
 static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
 				   u16 *caldata, int callen)
 {
@@ -319,6 +368,36 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
 	return ret;
 }
 
+static int sun8i_h3_thermal_init(struct ths_device *tmdev)
+{
+	int val;
+
+	/* average over 4 samples */
+	regmap_write(tmdev->regmap, SUN8I_THS_MFC,
+		     SUN50I_THS_FILTER_EN |
+		     SUN50I_THS_FILTER_TYPE(1));
+	/*
+	 * period = (x + 1) * 4096 / clkin; ~10ms
+	 * enable data interrupt
+	 */
+	val = GENMASK(7 + tmdev->chip->sensor_num, 8);
+	regmap_write(tmdev->regmap, SUN8I_THS_IC,
+		     SUN50I_H6_THS_PC_TEMP_PERIOD(58) | val);
+	/*
+	 * clkin = 24MHz
+	 * T acquire = clkin / (x + 1)
+	 *           = 20us
+	 * enable sensor
+	 */
+	regmap_write(tmdev->regmap, SUN8I_THS_CTRL0,
+		     SUN8I_THS_CTRL0_T_ACQ0(479));
+	val = GENMASK(tmdev->chip->sensor_num - 1, 0);
+	regmap_write(tmdev->regmap, SUN8I_THS_CTRL2,
+		     SUN8I_THS_CTRL2_T_ACQ1(479) | val);
+
+	return 0;
+}
+
 static int sun50i_h6_thermal_init(struct ths_device *tmdev)
 {
 	int val;
@@ -425,6 +504,17 @@ static int sun8i_ths_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct ths_thermal_chip sun8i_h3_ths = {
+	.sensor_num = 1,
+	.offset = -1794,
+	.scale = -121,
+	.has_mod_clk = true,
+	.temp_data_base = SUN8I_THS_TEMP_DATA,
+	.calibrate = sun8i_h3_ths_calibrate,
+	.init = sun8i_h3_thermal_init,
+	.irq_ack = sun8i_h3_irq_ack,
+};
+
 static const struct ths_thermal_chip sun50i_h6_ths = {
 	.sensor_num = 2,
 	.offset = -2794,
@@ -437,6 +527,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
 };
 
 static const struct of_device_id of_ths_match[] = {
+	{ .compatible = "allwinner,sun8i-h3-ths", .data = &sun8i_h3_ths },
 	{ .compatible = "allwinner,sun50i-h6-ths", .data = &sun50i_h6_ths },
 	{ /* sentinel */ },
 };
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 12/18] dt-bindings: thermal: add binding document for a64 thermal controller
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (10 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 11/18] thermal: sun8i: add thermal driver for h3 Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-27 15:26   ` Rob Herring
  2019-08-10  5:28 ` [PATCH v5 13/18] thermal: sun8i: add thermal driver for A64 Yangtao Li
                   ` (7 subsequent siblings)
  19 siblings, 1 reply; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

This patch adds binding document for allwinner a64 thermal controller.

Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
---
 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
index 6624cf6b1ce8..f935b4fab8ec 100644
--- a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
@@ -17,6 +17,7 @@ properties:
   compatible:
     enum:
       - allwinner,sun8i-h3-ths
+      - allwinner,sun50i-a64-ths
       - allwinner,sun50i-h6-ths
 
   reg:
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 13/18] thermal: sun8i: add thermal driver for A64
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (11 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 12/18] dt-bindings: thermal: add binding document for a64 thermal controller Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-10  5:28 ` [PATCH v5 14/18] dt-bindings: thermal: add binding document for h5 thermal controller Yangtao Li
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Vasily Khoruzhick

From: Vasily Khoruzhick <anarsoul@gmail.com>

Thermal sensor controller in A64 is similar to H3, but it has 3 sensors.
Extend H3 functions to add support for multiple sensors.

Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
---
 drivers/thermal/sun8i_thermal.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 41ce8cdc0546..3259081da841 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -515,6 +515,17 @@ static const struct ths_thermal_chip sun8i_h3_ths = {
 	.irq_ack = sun8i_h3_irq_ack,
 };
 
+static const struct ths_thermal_chip sun50i_a64_ths = {
+	.sensor_num = 3,
+	.offset = -2170,
+	.scale = -117,
+	.has_mod_clk = true,
+	.temp_data_base = SUN8I_THS_TEMP_DATA,
+	.calibrate = sun8i_h3_ths_calibrate,
+	.init = sun8i_h3_thermal_init,
+	.irq_ack = sun8i_h3_irq_ack,
+};
+
 static const struct ths_thermal_chip sun50i_h6_ths = {
 	.sensor_num = 2,
 	.offset = -2794,
@@ -528,6 +539,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
 
 static const struct of_device_id of_ths_match[] = {
 	{ .compatible = "allwinner,sun8i-h3-ths", .data = &sun8i_h3_ths },
+	{ .compatible = "allwinner,sun50i-a64-ths", .data = &sun50i_a64_ths },
 	{ .compatible = "allwinner,sun50i-h6-ths", .data = &sun50i_h6_ths },
 	{ /* sentinel */ },
 };
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 14/18] dt-bindings: thermal: add binding document for h5 thermal controller
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (12 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 13/18] thermal: sun8i: add thermal driver for A64 Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-27 15:27   ` Rob Herring
  2019-08-10  5:28 ` [PATCH v5 15/18] thermal: sun8i: allow to use custom temperature calculation function Yangtao Li
                   ` (5 subsequent siblings)
  19 siblings, 1 reply; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

This patch adds binding document for allwinner h5 thermal controller.

Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
---
 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
index f935b4fab8ec..2e28f5b33d33 100644
--- a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
@@ -18,6 +18,7 @@ properties:
     enum:
       - allwinner,sun8i-h3-ths
       - allwinner,sun50i-a64-ths
+      - allwinner,sun50i-h5-ths
       - allwinner,sun50i-h6-ths
 
   reg:
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 15/18] thermal: sun8i: allow to use custom temperature calculation function
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (13 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 14/18] dt-bindings: thermal: add binding document for h5 thermal controller Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-12  8:49   ` Maxime Ripard
  2019-08-10  5:28 ` [PATCH v5 16/18] thermal: sun8i: add support for Allwinner H5 thermal sensor Yangtao Li
                   ` (4 subsequent siblings)
  19 siblings, 1 reply; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Icenowy Zheng

From: Icenowy Zheng <icenowy@aosc.io>

The H5 temperature calculation function is strange. Firstly, it's
segmented. Secondly, the formula of two sensors are different in the
second segment.

Allow to use a custom temperature calculation function, in case of
the function is complex.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
 drivers/thermal/sun8i_thermal.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 3259081da841..a761e2afda08 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -76,6 +76,7 @@ struct ths_thermal_chip {
 				     u16 *caldata, int callen);
 	int		(*init)(struct ths_device *tmdev);
 	int             (*irq_ack)(struct ths_device *tmdev);
+	int		(*calc_temp)(int id, int reg);
 };
 
 struct ths_device {
@@ -90,9 +91,12 @@ struct ths_device {
 
 /* Temp Unit: millidegree Celsius */
 static int sun8i_ths_reg2temp(struct ths_device *tmdev,
-			      int reg)
+			      int id, int reg)
 {
-	return (reg + tmdev->chip->offset) * tmdev->chip->scale;
+	if (tmdev->chip->calc_temp)
+		return tmdev->chip->calc_temp(id, reg);
+	else
+		return (reg + tmdev->chip->offset) * tmdev->chip->scale;
 }
 
 static int sun8i_ths_get_temp(void *data, int *temp)
@@ -108,7 +112,7 @@ static int sun8i_ths_get_temp(void *data, int *temp)
 	if (!val)
 		return -EAGAIN;
 
-	*temp = sun8i_ths_reg2temp(tmdev, val);
+	*temp = sun8i_ths_reg2temp(tmdev, s->id, val);
 	/*
 	 * XX - According to the original sdk, there are some platforms(rarely)
 	 * that add a fixed offset value after calculating the temperature
@@ -232,7 +236,7 @@ static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
 
 	for (i = 0; i < tmdev->chip->sensor_num; i++) {
 		int reg = (int)caldata[i + 1];
-		int sensor_temp = sun8i_ths_reg2temp(tmdev, reg);
+		int sensor_temp = sun8i_ths_reg2temp(tmdev, i, reg);
 		int delta, cdata, offset;
 
 		/*
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 16/18] thermal: sun8i: add support for Allwinner H5 thermal sensor
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (14 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 15/18] thermal: sun8i: allow to use custom temperature calculation function Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-10  5:28 ` [PATCH v5 17/18] dt-bindings: thermal: add binding document for r40 thermal controller Yangtao Li
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Icenowy Zheng

From: Icenowy Zheng <icenowy@aosc.io>

The thermal sensor in Allwinner H5 has 2 sensors, and they have a
special segmented temperature calculation formula.

Add support for this thermal sensor.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
 drivers/thermal/sun8i_thermal.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index a761e2afda08..78a888d85cba 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -99,6 +99,16 @@ static int sun8i_ths_reg2temp(struct ths_device *tmdev,
 		return (reg + tmdev->chip->offset) * tmdev->chip->scale;
 }
 
+static int sun50i_h5_calc_temp(int id, int reg)
+{
+	if (reg >= 0x500)
+		return -1191 * reg / 10 + 223000;
+	else if (!id)
+		return -1452 * reg / 10 + 259000;
+	else
+		return -1590 * reg / 10 + 276000;
+}
+
 static int sun8i_ths_get_temp(void *data, int *temp)
 {
 	struct tsensor *s = data;
@@ -530,6 +540,16 @@ static const struct ths_thermal_chip sun50i_a64_ths = {
 	.irq_ack = sun8i_h3_irq_ack,
 };
 
+static const struct ths_thermal_chip sun50i_h5_ths = {
+	.sensor_num = 2,
+	.has_mod_clk = true,
+	.temp_data_base = SUN8I_THS_TEMP_DATA,
+	.calibrate = sun8i_h3_ths_calibrate,
+	.init = sun8i_h3_thermal_init,
+	.irq_ack = sun8i_h3_irq_ack,
+	.calc_temp = sun50i_h5_calc_temp,
+};
+
 static const struct ths_thermal_chip sun50i_h6_ths = {
 	.sensor_num = 2,
 	.offset = -2794,
@@ -544,6 +564,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
 static const struct of_device_id of_ths_match[] = {
 	{ .compatible = "allwinner,sun8i-h3-ths", .data = &sun8i_h3_ths },
 	{ .compatible = "allwinner,sun50i-a64-ths", .data = &sun50i_a64_ths },
+	{ .compatible = "allwinner,sun50i-h5-ths", .data = &sun50i_h5_ths },
 	{ .compatible = "allwinner,sun50i-h6-ths", .data = &sun50i_h6_ths },
 	{ /* sentinel */ },
 };
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 17/18] dt-bindings: thermal: add binding document for r40 thermal controller
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (15 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 16/18] thermal: sun8i: add support for Allwinner H5 thermal sensor Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-27 15:27   ` Rob Herring
  2019-08-10  5:28 ` [PATCH v5 18/18] thermal: sun8i: add support for Allwinner R40 thermal sensor Yangtao Li
                   ` (2 subsequent siblings)
  19 siblings, 1 reply; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

This patch adds binding document for allwinner r40 thermal controller.

Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
---
 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
index 2e28f5b33d33..28c438d3bfea 100644
--- a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
@@ -17,6 +17,7 @@ properties:
   compatible:
     enum:
       - allwinner,sun8i-h3-ths
+      - allwinner,sun8i-r40-ths
       - allwinner,sun50i-a64-ths
       - allwinner,sun50i-h5-ths
       - allwinner,sun50i-h6-ths
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH v5 18/18] thermal: sun8i: add support for Allwinner R40 thermal sensor
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (16 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 17/18] dt-bindings: thermal: add binding document for r40 thermal controller Yangtao Li
@ 2019-08-10  5:28 ` Yangtao Li
  2019-08-11 21:14 ` [PATCH v5 00/18] add thermal driver for h6 Clément Péron
  2019-09-01 21:52 ` Ondřej Jirman
  19 siblings, 0 replies; 43+ messages in thread
From: Yangtao Li @ 2019-08-10  5:28 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Icenowy Zheng

From: Icenowy Zheng <icenowy@aosc.io>

The thermal sensor in Allwinner R40 SoC is quite similar to the one in
Allwinner A64 SoC, with only slightly different temperature calculation
formula.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
 drivers/thermal/sun8i_thermal.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 78a888d85cba..0de9a56c3775 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -529,6 +529,17 @@ static const struct ths_thermal_chip sun8i_h3_ths = {
 	.irq_ack = sun8i_h3_irq_ack,
 };
 
+static const struct ths_thermal_chip sun8i_r40_ths = {
+	.sensor_num = 3,
+	.offset = -2222,
+	.scale = -113,
+	.has_mod_clk = true,
+	.temp_data_base = SUN8I_THS_TEMP_DATA,
+	.calibrate = sun8i_h3_ths_calibrate,
+	.init = sun8i_h3_thermal_init,
+	.irq_ack = sun8i_h3_irq_ack,
+};
+
 static const struct ths_thermal_chip sun50i_a64_ths = {
 	.sensor_num = 3,
 	.offset = -2170,
@@ -563,6 +574,7 @@ static const struct ths_thermal_chip sun50i_h6_ths = {
 
 static const struct of_device_id of_ths_match[] = {
 	{ .compatible = "allwinner,sun8i-h3-ths", .data = &sun8i_h3_ths },
+	{ .compatible = "allwinner,sun8i-r40-ths", .data = &sun8i_r40_ths },
 	{ .compatible = "allwinner,sun50i-a64-ths", .data = &sun50i_a64_ths },
 	{ .compatible = "allwinner,sun50i-h5-ths", .data = &sun50i_h5_ths },
 	{ .compatible = "allwinner,sun50i-h6-ths", .data = &sun50i_h6_ths },
-- 
2.17.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 08/18] thermal: sun8i: support mod clocks
  2019-08-10  5:28 ` [PATCH v5 08/18] thermal: sun8i: support mod clocks Yangtao Li
@ 2019-08-10  6:16   ` Vasily Khoruzhick
  2019-08-12 23:46     ` Frank Lee
  0 siblings, 1 reply; 43+ messages in thread
From: Vasily Khoruzhick @ 2019-08-10  6:16 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, Eduardo Valentin, Daniel Lezcano, Rob Herring,
	Mark Rutland, Maxime Ripard, Chen-Yu Tsai, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Jonathan.Cameron,
	Nicolas Ferre, devicetree, linux-kernel, arm-linux, Linux PM

On Fri, Aug 9, 2019 at 10:31 PM Yangtao Li <tiny.windzz@gmail.com> wrote:
>
> H3 has extra clock, so introduce something in ths_thermal_chip/ths_device
> and adds the process of the clock.
>
> This is pre-work for supprt it.
>
> Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> ---
>  drivers/thermal/sun8i_thermal.c | 17 ++++++++++++++++-
>  1 file changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
> index b934bc81eba7..6f4294c2aba7 100644
> --- a/drivers/thermal/sun8i_thermal.c
> +++ b/drivers/thermal/sun8i_thermal.c
> @@ -54,6 +54,7 @@ struct tsensor {
>  };
>
>  struct ths_thermal_chip {
> +       bool            has_mod_clk;
>         int             sensor_num;
>         int             offset;
>         int             scale;
> @@ -69,6 +70,7 @@ struct ths_device {
>         struct regmap                           *regmap;
>         struct reset_control                    *reset;
>         struct clk                              *bus_clk;
> +       struct clk                              *mod_clk;
>         struct tsensor                          sensor[MAX_SENSOR_NUM];
>  };
>
> @@ -274,6 +276,12 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
>         if (IS_ERR(tmdev->bus_clk))
>                 return PTR_ERR(tmdev->bus_clk);
>
> +       if (tmdev->chip->has_mod_clk) {
> +               tmdev->mod_clk = devm_clk_get(&pdev->dev, "mod");
> +               if (IS_ERR(tmdev->mod_clk))
> +                       return PTR_ERR(tmdev->mod_clk);
> +       }
> +
>         ret = reset_control_deassert(tmdev->reset);
>         if (ret)
>                 return ret;
> @@ -282,12 +290,18 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
>         if (ret)
>                 goto assert_reset;
>
> -       ret = sun50i_ths_calibrate(tmdev);
> +       ret = clk_prepare_enable(tmdev->mod_clk);

You have to set rate of modclk before enabling it since you can't rely
on whatever bootloader left for you.

Also I found that parameters you're using for PC_TEMP_PERIOD, ACQ0 and
ACQ1 are too aggressive and may result in high interrupt rate to the
point when it may stall RCU. I changed driver a bit to use params from
Philipp Rossak's work (modclk set to 4MHz, PC_TEMP_PERIOD is 7, ACQ0
is 255, ACQ1 is 63) and it fixed RCU stalls for me, see [1] for
details.

[1] https://github.com/anarsoul/linux-2.6/commit/46b8bb0fe2ccd1cd88fa9181a2ecbf79e8d513b2


>         if (ret)
>                 goto bus_disable;
>
> +       ret = sun50i_ths_calibrate(tmdev);
> +       if (ret)
> +               goto mod_disable;
> +
>         return 0;
>
> +mod_disable:
> +       clk_disable_unprepare(tmdev->mod_clk);
>  bus_disable:
>         clk_disable_unprepare(tmdev->bus_clk);
>  assert_reset:
> @@ -395,6 +409,7 @@ static int sun8i_ths_remove(struct platform_device *pdev)
>  {
>         struct ths_device *tmdev = platform_get_drvdata(pdev);
>
> +       clk_disable_unprepare(tmdev->mod_clk);
>         clk_disable_unprepare(tmdev->bus_clk);
>         reset_control_assert(tmdev->reset);
>
> --
> 2.17.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 00/18] add thermal driver for h6
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (17 preceding siblings ...)
  2019-08-10  5:28 ` [PATCH v5 18/18] thermal: sun8i: add support for Allwinner R40 thermal sensor Yangtao Li
@ 2019-08-11 21:14 ` Clément Péron
  2019-08-12 23:36   ` Frank Lee
  2019-09-01 21:52 ` Ondřej Jirman
  19 siblings, 1 reply; 43+ messages in thread
From: Clément Péron @ 2019-08-11 21:14 UTC (permalink / raw)
  To: Yangtao Li, rui.zhang, edubezval, daniel.lezcano, robh+dt,
	mark.rutland, maxime.ripard, wens, mchehab+samsung, davem,
	gregkh, Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel

Hi Yangtao,

On 10/08/2019 07:28, Yangtao Li wrote:
> This patchset add support for A64, H3, H5, H6 and R40 thermal sensor.

Could you add the device-tree configuration in the same series?
This will allow user to test it.

Thanks,
Clément

> 
> Thx to Icenowy and Vasily.
> 
> BTY, do a cleanup in thermal makfile.
> 
> Icenowy Zheng (3):
>    thermal: sun8i: allow to use custom temperature calculation function
>    thermal: sun8i: add support for Allwinner H5 thermal sensor
>    thermal: sun8i: add support for Allwinner R40 thermal sensor
> 
> Vasily Khoruzhick (1):
>    thermal: sun8i: add thermal driver for A64
> 
> Yangtao Li (14):
>    thermal: sun8i: add thermal driver for h6
>    dt-bindings: thermal: add binding document for h6 thermal controller
>    thermal: fix indentation in makefile
>    thermal: sun8i: get ths sensor number from device compatible
>    thermal: sun8i: rework for sun8i_ths_get_temp()
>    thermal: sun8i: get ths init func from device compatible
>    thermal: sun8i: rework for ths irq handler func
>    thermal: sun8i: support mod clocks
>    thermal: sun8i: rework for ths calibrate func
>    dt-bindings: thermal: add binding document for h3 thermal controller
>    thermal: sun8i: add thermal driver for h3
>    dt-bindings: thermal: add binding document for a64 thermal controller
>    dt-bindings: thermal: add binding document for h5 thermal controller
>    dt-bindings: thermal: add binding document for r40 thermal controller
> 
>   .../bindings/thermal/sun8i-thermal.yaml       | 157 +++++
>   MAINTAINERS                                   |   7 +
>   drivers/thermal/Kconfig                       |  14 +
>   drivers/thermal/Makefile                      |   9 +-
>   drivers/thermal/sun8i_thermal.c               | 596 ++++++++++++++++++
>   5 files changed, 779 insertions(+), 4 deletions(-)
>   create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
>   create mode 100644 drivers/thermal/sun8i_thermal.c
> ---
> v5:
> -add more support
> -some trival fix
> ---
> 2.17.1
> 
> 

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 15/18] thermal: sun8i: allow to use custom temperature calculation function
  2019-08-10  5:28 ` [PATCH v5 15/18] thermal: sun8i: allow to use custom temperature calculation function Yangtao Li
@ 2019-08-12  8:49   ` Maxime Ripard
  0 siblings, 0 replies; 43+ messages in thread
From: Maxime Ripard @ 2019-08-12  8:49 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	wens, mchehab+samsung, davem, gregkh, Jonathan.Cameron,
	nicolas.ferre, linux-pm, devicetree, linux-arm-kernel,
	linux-kernel, Icenowy Zheng

[-- Attachment #1: Type: text/plain, Size: 2076 bytes --]

Hi,

On Sat, Aug 10, 2019 at 05:28:26AM +0000, Yangtao Li wrote:
> From: Icenowy Zheng <icenowy@aosc.io>
>
> The H5 temperature calculation function is strange. Firstly, it's
> segmented. Secondly, the formula of two sensors are different in the
> second segment.
>
> Allow to use a custom temperature calculation function, in case of
> the function is complex.
>
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>

When you send a patch on someone else's behalf, you need to put your
Signed-off-by as well.

> ---
>  drivers/thermal/sun8i_thermal.c | 12 ++++++++----
>  1 file changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
> index 3259081da841..a761e2afda08 100644
> --- a/drivers/thermal/sun8i_thermal.c
> +++ b/drivers/thermal/sun8i_thermal.c
> @@ -76,6 +76,7 @@ struct ths_thermal_chip {
>  				     u16 *caldata, int callen);
>  	int		(*init)(struct ths_device *tmdev);
>  	int             (*irq_ack)(struct ths_device *tmdev);
> +	int		(*calc_temp)(int id, int reg);
>  };
>
>  struct ths_device {
> @@ -90,9 +91,12 @@ struct ths_device {
>
>  /* Temp Unit: millidegree Celsius */
>  static int sun8i_ths_reg2temp(struct ths_device *tmdev,
> -			      int reg)
> +			      int id, int reg)
>  {
> -	return (reg + tmdev->chip->offset) * tmdev->chip->scale;
> +	if (tmdev->chip->calc_temp)
> +		return tmdev->chip->calc_temp(id, reg);
> +	else
> +		return (reg + tmdev->chip->offset) * tmdev->chip->scale;

You're not consistent here compared to the other callbacks you have
introduced: calibrate, init and irq_ack all need to be set and will
fail (hard) if you don't set them, yet this one will have a different
behaviour (that behaviour being to use the H6 formula, which is the
latest SoC, which is a bit odd in itself).

I guess we should either make it mandatory as the rest of the
callbacks, or document which callbacks are mandatory and which are
optional (and the behaviour when it's optional).

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 02/18] dt-bindings: thermal: add binding document for h6 thermal controller
  2019-08-10  5:28 ` [PATCH v5 02/18] dt-bindings: thermal: add binding document for h6 thermal controller Yangtao Li
@ 2019-08-12  8:56   ` Maxime Ripard
  2019-08-12 23:40     ` Frank Lee
  0 siblings, 1 reply; 43+ messages in thread
From: Maxime Ripard @ 2019-08-12  8:56 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	wens, mchehab+samsung, davem, gregkh, Jonathan.Cameron,
	nicolas.ferre, linux-pm, devicetree, linux-arm-kernel,
	linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2562 bytes --]

On Sat, Aug 10, 2019 at 05:28:13AM +0000, Yangtao Li wrote:
> This patch adds binding document for allwinner h6 thermal controller.
>
> Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> ---
>  .../bindings/thermal/sun8i-thermal.yaml       | 79 +++++++++++++++++++
>  1 file changed, 79 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
>
> diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
> new file mode 100644
> index 000000000000..e0973199ba3c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml

We've used so far for the schemas the first compatible to introduce
that controller as the filename, we should be consistent here. In that
case that would be allwinner,sun8i-a23-ths.yaml

> @@ -0,0 +1,79 @@
> +# SPDX-License-Identifier: GPL-2.0
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/thermal/sun8i-thermal.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Allwinner SUN8I Thermal Controller Device Tree Bindings
> +
> +maintainers:
> +  - Yangtao Li <tiny.windzz@gmail.com>
> +
> +description: |-
> +  This describes the device tree binding for the Allwinner thermal
> +  controller which measures the on-SoC temperatures.
> +
> +properties:
> +  compatible:
> +    enum:
> +      - allwinner,sun50i-h6-ths
> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  resets:
> +    maxItems: 1
> +
> +  clocks:
> +    maxItems: 1
> +
> +  clock-names:
> +    const: bus
> +
> +  "#thermal-sensor-cells":
> +    const: 1
> +
> +  nvmem-cells:

You need a maxItems here too

> +    description: ths calibrate data

What about something like this:

Calibration data for the thermal sensor

> +
> +  nvmem-cell-names:
> +    const: calib

I'm not sure we need a abbreviation here, calibration would be more
explicit

> +
> +required:
> +  - compatible
> +  - reg
> +  - reset
> +  - clocks
> +  - clock-names
> +  - interrupts
> +  - "#thermal-sensor-cells"
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    ths: ths@5070400 {
> +        compatible = "allwinner,sun50i-h6-ths";
> +        reg = <0x05070400 0x100>;
> +        clocks = <&ccu CLK_BUS_THS>;
> +        clock-names = "bus";
> +        resets = <&ccu RST_BUS_THS>;
> +        interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;

Those examples won't compile.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 00/18] add thermal driver for h6
  2019-08-11 21:14 ` [PATCH v5 00/18] add thermal driver for h6 Clément Péron
@ 2019-08-12 23:36   ` Frank Lee
  0 siblings, 0 replies; 43+ messages in thread
From: Frank Lee @ 2019-08-12 23:36 UTC (permalink / raw)
  To: Clément Péron
  Cc: rui.zhang, Eduardo Valentin, Daniel Lezcano, Rob Herring,
	Mark Rutland, Maxime Ripard, Chen-Yu Tsai, Mauro Carvalho Chehab,
	David Miller, Greg Kroah-Hartman, Jonathan.Cameron,
	Nicolas Ferre, Linux PM, devicetree, Linux ARM,
	Linux Kernel Mailing List

On Mon, Aug 12, 2019 at 5:14 AM Clément Péron <peron.clem@gmail.com> wrote:
>
> Hi Yangtao,
>
> On 10/08/2019 07:28, Yangtao Li wrote:
> > This patchset add support for A64, H3, H5, H6 and R40 thermal sensor.
>
> Could you add the device-tree configuration in the same series?
> This will allow user to test it.

Ok, it will be added later.

Yangtao

>
> Thanks,
> Clément
>
> >
> > Thx to Icenowy and Vasily.
> >
> > BTY, do a cleanup in thermal makfile.
> >
> > Icenowy Zheng (3):
> >    thermal: sun8i: allow to use custom temperature calculation function
> >    thermal: sun8i: add support for Allwinner H5 thermal sensor
> >    thermal: sun8i: add support for Allwinner R40 thermal sensor
> >
> > Vasily Khoruzhick (1):
> >    thermal: sun8i: add thermal driver for A64
> >
> > Yangtao Li (14):
> >    thermal: sun8i: add thermal driver for h6
> >    dt-bindings: thermal: add binding document for h6 thermal controller
> >    thermal: fix indentation in makefile
> >    thermal: sun8i: get ths sensor number from device compatible
> >    thermal: sun8i: rework for sun8i_ths_get_temp()
> >    thermal: sun8i: get ths init func from device compatible
> >    thermal: sun8i: rework for ths irq handler func
> >    thermal: sun8i: support mod clocks
> >    thermal: sun8i: rework for ths calibrate func
> >    dt-bindings: thermal: add binding document for h3 thermal controller
> >    thermal: sun8i: add thermal driver for h3
> >    dt-bindings: thermal: add binding document for a64 thermal controller
> >    dt-bindings: thermal: add binding document for h5 thermal controller
> >    dt-bindings: thermal: add binding document for r40 thermal controller
> >
> >   .../bindings/thermal/sun8i-thermal.yaml       | 157 +++++
> >   MAINTAINERS                                   |   7 +
> >   drivers/thermal/Kconfig                       |  14 +
> >   drivers/thermal/Makefile                      |   9 +-
> >   drivers/thermal/sun8i_thermal.c               | 596 ++++++++++++++++++
> >   5 files changed, 779 insertions(+), 4 deletions(-)
> >   create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
> >   create mode 100644 drivers/thermal/sun8i_thermal.c
> > ---
> > v5:
> > -add more support
> > -some trival fix
> > ---
> > 2.17.1
> >
> >

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 02/18] dt-bindings: thermal: add binding document for h6 thermal controller
  2019-08-12  8:56   ` Maxime Ripard
@ 2019-08-12 23:40     ` Frank Lee
  2019-08-16  9:47       ` Maxime Ripard
  0 siblings, 1 reply; 43+ messages in thread
From: Frank Lee @ 2019-08-12 23:40 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: rui.zhang, Eduardo Valentin, Daniel Lezcano, Rob Herring,
	Mark Rutland, Chen-Yu Tsai, Mauro Carvalho Chehab, David Miller,
	Greg Kroah-Hartman, Jonathan.Cameron, Nicolas Ferre, Linux PM,
	devicetree, Linux ARM, Linux Kernel Mailing List

On Mon, Aug 12, 2019 at 4:56 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
>
> On Sat, Aug 10, 2019 at 05:28:13AM +0000, Yangtao Li wrote:
> > This patch adds binding document for allwinner h6 thermal controller.
> >
> > Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> > ---
> >  .../bindings/thermal/sun8i-thermal.yaml       | 79 +++++++++++++++++++
> >  1 file changed, 79 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
> > new file mode 100644
> > index 000000000000..e0973199ba3c
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
>
> We've used so far for the schemas the first compatible to introduce
> that controller as the filename, we should be consistent here. In that
> case that would be allwinner,sun8i-a23-ths.yaml
>
> > @@ -0,0 +1,79 @@
> > +# SPDX-License-Identifier: GPL-2.0
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/thermal/sun8i-thermal.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Allwinner SUN8I Thermal Controller Device Tree Bindings
> > +
> > +maintainers:
> > +  - Yangtao Li <tiny.windzz@gmail.com>
> > +
> > +description: |-
> > +  This describes the device tree binding for the Allwinner thermal
> > +  controller which measures the on-SoC temperatures.
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - allwinner,sun50i-h6-ths
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  interrupts:
> > +    maxItems: 1
> > +
> > +  resets:
> > +    maxItems: 1
> > +
> > +  clocks:
> > +    maxItems: 1
> > +
> > +  clock-names:
> > +    const: bus
> > +
> > +  "#thermal-sensor-cells":
> > +    const: 1
> > +
> > +  nvmem-cells:
>
> You need a maxItems here too
>
> > +    description: ths calibrate data
>
> What about something like this:
>
> Calibration data for the thermal sensor
>
> > +
> > +  nvmem-cell-names:
> > +    const: calib
>
> I'm not sure we need a abbreviation here, calibration would be more
> explicit
>
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - reset
> > +  - clocks
> > +  - clock-names
> > +  - interrupts
> > +  - "#thermal-sensor-cells"
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    ths: ths@5070400 {
> > +        compatible = "allwinner,sun50i-h6-ths";
> > +        reg = <0x05070400 0x100>;
> > +        clocks = <&ccu CLK_BUS_THS>;
> > +        clock-names = "bus";
> > +        resets = <&ccu RST_BUS_THS>;
> > +        interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
>
> Those examples won't compile.

Emmm, I have some questions about this.
I added this information and it can be compiled.

Yours,
Yangtao

>
> Maxime
>
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 08/18] thermal: sun8i: support mod clocks
  2019-08-10  6:16   ` Vasily Khoruzhick
@ 2019-08-12 23:46     ` Frank Lee
  2019-08-12 23:54       ` Vasily Khoruzhick
  0 siblings, 1 reply; 43+ messages in thread
From: Frank Lee @ 2019-08-12 23:46 UTC (permalink / raw)
  To: Vasily Khoruzhick
  Cc: rui.zhang, Eduardo Valentin, Daniel Lezcano, Rob Herring,
	Mark Rutland, Maxime Ripard, Chen-Yu Tsai, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Jonathan.Cameron,
	Nicolas Ferre, devicetree, linux-kernel, arm-linux, Linux PM

HI Vasily,

On Sat, Aug 10, 2019 at 2:17 PM Vasily Khoruzhick <anarsoul@gmail.com> wrote:
>
> On Fri, Aug 9, 2019 at 10:31 PM Yangtao Li <tiny.windzz@gmail.com> wrote:
> >
> > H3 has extra clock, so introduce something in ths_thermal_chip/ths_device
> > and adds the process of the clock.
> >
> > This is pre-work for supprt it.
> >
> > Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> > ---
> >  drivers/thermal/sun8i_thermal.c | 17 ++++++++++++++++-
> >  1 file changed, 16 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
> > index b934bc81eba7..6f4294c2aba7 100644
> > --- a/drivers/thermal/sun8i_thermal.c
> > +++ b/drivers/thermal/sun8i_thermal.c
> > @@ -54,6 +54,7 @@ struct tsensor {
> >  };
> >
> >  struct ths_thermal_chip {
> > +       bool            has_mod_clk;
> >         int             sensor_num;
> >         int             offset;
> >         int             scale;
> > @@ -69,6 +70,7 @@ struct ths_device {
> >         struct regmap                           *regmap;
> >         struct reset_control                    *reset;
> >         struct clk                              *bus_clk;
> > +       struct clk                              *mod_clk;
> >         struct tsensor                          sensor[MAX_SENSOR_NUM];
> >  };
> >
> > @@ -274,6 +276,12 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
> >         if (IS_ERR(tmdev->bus_clk))
> >                 return PTR_ERR(tmdev->bus_clk);
> >
> > +       if (tmdev->chip->has_mod_clk) {
> > +               tmdev->mod_clk = devm_clk_get(&pdev->dev, "mod");
> > +               if (IS_ERR(tmdev->mod_clk))
> > +                       return PTR_ERR(tmdev->mod_clk);
> > +       }
> > +
> >         ret = reset_control_deassert(tmdev->reset);
> >         if (ret)
> >                 return ret;
> > @@ -282,12 +290,18 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
> >         if (ret)
> >                 goto assert_reset;
> >
> > -       ret = sun50i_ths_calibrate(tmdev);
> > +       ret = clk_prepare_enable(tmdev->mod_clk);
>
> You have to set rate of modclk before enabling it since you can't rely
> on whatever bootloader left for you.
>
> Also I found that parameters you're using for PC_TEMP_PERIOD, ACQ0 and
> ACQ1 are too aggressive and may result in high interrupt rate to the
> point when it may stall RCU. I changed driver a bit to use params from
> Philipp Rossak's work (modclk set to 4MHz, PC_TEMP_PERIOD is 7, ACQ0
> is 255, ACQ1 is 63) and it fixed RCU stalls for me, see [1] for
> details.

Why is the RCU stall happening, is it caused by a deadlock?
Can you provide log information and your configuration?
I am a bit curious.

Thx,
Yangtao

>
> [1] https://github.com/anarsoul/linux-2.6/commit/46b8bb0fe2ccd1cd88fa9181a2ecbf79e8d513b2
>
>
> >         if (ret)
> >                 goto bus_disable;
> >
> > +       ret = sun50i_ths_calibrate(tmdev);
> > +       if (ret)
> > +               goto mod_disable;
> > +
> >         return 0;
> >
> > +mod_disable:
> > +       clk_disable_unprepare(tmdev->mod_clk);
> >  bus_disable:
> >         clk_disable_unprepare(tmdev->bus_clk);
> >  assert_reset:
> > @@ -395,6 +409,7 @@ static int sun8i_ths_remove(struct platform_device *pdev)
> >  {
> >         struct ths_device *tmdev = platform_get_drvdata(pdev);
> >
> > +       clk_disable_unprepare(tmdev->mod_clk);
> >         clk_disable_unprepare(tmdev->bus_clk);
> >         reset_control_assert(tmdev->reset);
> >
> > --
> > 2.17.1
> >
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 08/18] thermal: sun8i: support mod clocks
  2019-08-12 23:46     ` Frank Lee
@ 2019-08-12 23:54       ` Vasily Khoruzhick
  2019-08-13 20:06         ` Ondřej Jirman
  0 siblings, 1 reply; 43+ messages in thread
From: Vasily Khoruzhick @ 2019-08-12 23:54 UTC (permalink / raw)
  To: Frank Lee
  Cc: rui.zhang, Eduardo Valentin, Daniel Lezcano, Rob Herring,
	Mark Rutland, Maxime Ripard, Chen-Yu Tsai, Mauro Carvalho Chehab,
	David S. Miller, Greg Kroah-Hartman, Jonathan.Cameron,
	Nicolas Ferre, devicetree, linux-kernel, arm-linux, Linux PM

On Mon, Aug 12, 2019 at 4:46 PM Frank Lee <tiny.windzz@gmail.com> wrote:
>
> HI Vasily,
>
> On Sat, Aug 10, 2019 at 2:17 PM Vasily Khoruzhick <anarsoul@gmail.com> wrote:
> >
> > On Fri, Aug 9, 2019 at 10:31 PM Yangtao Li <tiny.windzz@gmail.com> wrote:
> > >
> > > H3 has extra clock, so introduce something in ths_thermal_chip/ths_device
> > > and adds the process of the clock.
> > >
> > > This is pre-work for supprt it.
> > >
> > > Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> > > ---
> > >  drivers/thermal/sun8i_thermal.c | 17 ++++++++++++++++-
> > >  1 file changed, 16 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
> > > index b934bc81eba7..6f4294c2aba7 100644
> > > --- a/drivers/thermal/sun8i_thermal.c
> > > +++ b/drivers/thermal/sun8i_thermal.c
> > > @@ -54,6 +54,7 @@ struct tsensor {
> > >  };
> > >
> > >  struct ths_thermal_chip {
> > > +       bool            has_mod_clk;
> > >         int             sensor_num;
> > >         int             offset;
> > >         int             scale;
> > > @@ -69,6 +70,7 @@ struct ths_device {
> > >         struct regmap                           *regmap;
> > >         struct reset_control                    *reset;
> > >         struct clk                              *bus_clk;
> > > +       struct clk                              *mod_clk;
> > >         struct tsensor                          sensor[MAX_SENSOR_NUM];
> > >  };
> > >
> > > @@ -274,6 +276,12 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
> > >         if (IS_ERR(tmdev->bus_clk))
> > >                 return PTR_ERR(tmdev->bus_clk);
> > >
> > > +       if (tmdev->chip->has_mod_clk) {
> > > +               tmdev->mod_clk = devm_clk_get(&pdev->dev, "mod");
> > > +               if (IS_ERR(tmdev->mod_clk))
> > > +                       return PTR_ERR(tmdev->mod_clk);
> > > +       }
> > > +
> > >         ret = reset_control_deassert(tmdev->reset);
> > >         if (ret)
> > >                 return ret;
> > > @@ -282,12 +290,18 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
> > >         if (ret)
> > >                 goto assert_reset;
> > >
> > > -       ret = sun50i_ths_calibrate(tmdev);
> > > +       ret = clk_prepare_enable(tmdev->mod_clk);
> >
> > You have to set rate of modclk before enabling it since you can't rely
> > on whatever bootloader left for you.
> >
> > Also I found that parameters you're using for PC_TEMP_PERIOD, ACQ0 and
> > ACQ1 are too aggressive and may result in high interrupt rate to the
> > point when it may stall RCU. I changed driver a bit to use params from
> > Philipp Rossak's work (modclk set to 4MHz, PC_TEMP_PERIOD is 7, ACQ0
> > is 255, ACQ1 is 63) and it fixed RCU stalls for me, see [1] for
> > details.
>
> Why is the RCU stall happening, is it caused by a deadlock?
> Can you provide log information and your configuration?
> I am a bit curious.

It's not deadlock, I believe it just can't handle that many interrupts
when running at lowest CPU frequency. Even with Philipp's settings
there's ~20 interrupts a second from ths. I don't remember how many
interrupts were there with your settings.

Unfortunately there's nothing interesting in backtraces, I'm using
Pine64-LTS board.

> Thx,
> Yangtao
>
> >
> > [1] https://github.com/anarsoul/linux-2.6/commit/46b8bb0fe2ccd1cd88fa9181a2ecbf79e8d513b2
> >
> >
> > >         if (ret)
> > >                 goto bus_disable;
> > >
> > > +       ret = sun50i_ths_calibrate(tmdev);
> > > +       if (ret)
> > > +               goto mod_disable;
> > > +
> > >         return 0;
> > >
> > > +mod_disable:
> > > +       clk_disable_unprepare(tmdev->mod_clk);
> > >  bus_disable:
> > >         clk_disable_unprepare(tmdev->bus_clk);
> > >  assert_reset:
> > > @@ -395,6 +409,7 @@ static int sun8i_ths_remove(struct platform_device *pdev)
> > >  {
> > >         struct ths_device *tmdev = platform_get_drvdata(pdev);
> > >
> > > +       clk_disable_unprepare(tmdev->mod_clk);
> > >         clk_disable_unprepare(tmdev->bus_clk);
> > >         reset_control_assert(tmdev->reset);
> > >
> > > --
> > > 2.17.1
> > >
> > >
> > > _______________________________________________
> > > linux-arm-kernel mailing list
> > > linux-arm-kernel@lists.infradead.org
> > > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 08/18] thermal: sun8i: support mod clocks
  2019-08-12 23:54       ` Vasily Khoruzhick
@ 2019-08-13 20:06         ` Ondřej Jirman
  2019-08-14  3:01           ` Vasily Khoruzhick
  0 siblings, 1 reply; 43+ messages in thread
From: Ondřej Jirman @ 2019-08-13 20:06 UTC (permalink / raw)
  To: Vasily Khoruzhick
  Cc: Frank Lee, Mark Rutland, devicetree, Linux PM, Maxime Ripard,
	Greg Kroah-Hartman, Daniel Lezcano, linux-kernel,
	Eduardo Valentin, Chen-Yu Tsai, Rob Herring, Jonathan.Cameron,
	Mauro Carvalho Chehab, rui.zhang, David S. Miller, arm-linux

On Mon, Aug 12, 2019 at 04:54:15PM -0700, Vasily Khoruzhick wrote:
> On Mon, Aug 12, 2019 at 4:46 PM Frank Lee <tiny.windzz@gmail.com> wrote:
> >
> > HI Vasily,
> >
> > On Sat, Aug 10, 2019 at 2:17 PM Vasily Khoruzhick <anarsoul@gmail.com> wrote:
> > >
> > > On Fri, Aug 9, 2019 at 10:31 PM Yangtao Li <tiny.windzz@gmail.com> wrote:
> > > >
> > > > H3 has extra clock, so introduce something in ths_thermal_chip/ths_device
> > > > and adds the process of the clock.
> > > >
> > > > This is pre-work for supprt it.
> > > >
> > > > Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> > > > ---
> > > >  drivers/thermal/sun8i_thermal.c | 17 ++++++++++++++++-
> > > >  1 file changed, 16 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
> > > > index b934bc81eba7..6f4294c2aba7 100644
> > > > --- a/drivers/thermal/sun8i_thermal.c
> > > > +++ b/drivers/thermal/sun8i_thermal.c
> > > > @@ -54,6 +54,7 @@ struct tsensor {
> > > >  };
> > > >
> > > >  struct ths_thermal_chip {
> > > > +       bool            has_mod_clk;
> > > >         int             sensor_num;
> > > >         int             offset;
> > > >         int             scale;
> > > > @@ -69,6 +70,7 @@ struct ths_device {
> > > >         struct regmap                           *regmap;
> > > >         struct reset_control                    *reset;
> > > >         struct clk                              *bus_clk;
> > > > +       struct clk                              *mod_clk;
> > > >         struct tsensor                          sensor[MAX_SENSOR_NUM];
> > > >  };
> > > >
> > > > @@ -274,6 +276,12 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
> > > >         if (IS_ERR(tmdev->bus_clk))
> > > >                 return PTR_ERR(tmdev->bus_clk);
> > > >
> > > > +       if (tmdev->chip->has_mod_clk) {
> > > > +               tmdev->mod_clk = devm_clk_get(&pdev->dev, "mod");
> > > > +               if (IS_ERR(tmdev->mod_clk))
> > > > +                       return PTR_ERR(tmdev->mod_clk);
> > > > +       }
> > > > +
> > > >         ret = reset_control_deassert(tmdev->reset);
> > > >         if (ret)
> > > >                 return ret;
> > > > @@ -282,12 +290,18 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
> > > >         if (ret)
> > > >                 goto assert_reset;
> > > >
> > > > -       ret = sun50i_ths_calibrate(tmdev);
> > > > +       ret = clk_prepare_enable(tmdev->mod_clk);
> > >
> > > You have to set rate of modclk before enabling it since you can't rely
> > > on whatever bootloader left for you.
> > >
> > > Also I found that parameters you're using for PC_TEMP_PERIOD, ACQ0 and
> > > ACQ1 are too aggressive and may result in high interrupt rate to the
> > > point when it may stall RCU. I changed driver a bit to use params from
> > > Philipp Rossak's work (modclk set to 4MHz, PC_TEMP_PERIOD is 7, ACQ0
> > > is 255, ACQ1 is 63) and it fixed RCU stalls for me, see [1] for
> > > details.
> >
> > Why is the RCU stall happening, is it caused by a deadlock?
> > Can you provide log information and your configuration?
> > I am a bit curious.
> 
> It's not deadlock, I believe it just can't handle that many interrupts
> when running at lowest CPU frequency. Even with Philipp's settings
> there's ~20 interrupts a second from ths. I don't remember how many
> interrupts were there with your settings.
> 
> Unfortunately there's nothing interesting in backtraces, I'm using
> Pine64-LTS board.

Recently there was a similar issue, with buggy CCU driver that caused
CIR interrupts being fired constantly, and it also resulted in RCU
stalls. Looks like a comon cause of RCU stalls.

THS timing settings probably need to be made specific to the SoC, because
I noticed that the same settings lead to wildly different timings on
different SoCs.

It would be good to measure how often ths interrupt fires with this driver
on various SoCs.

20 times a second and more sounds like overkill. I'd expect a useful
range to be at most 5-10 times a second. That should be enough to stop
overheating the SoC due to suddenly increased load, even without a
heatsink.

regards,
	o.

> > Thx,
> > Yangtao
> >
> > >
> > > [1] https://github.com/anarsoul/linux-2.6/commit/46b8bb0fe2ccd1cd88fa9181a2ecbf79e8d513b2
> > >
> > >
> > > >         if (ret)
> > > >                 goto bus_disable;
> > > >
> > > > +       ret = sun50i_ths_calibrate(tmdev);
> > > > +       if (ret)
> > > > +               goto mod_disable;
> > > > +
> > > >         return 0;
> > > >
> > > > +mod_disable:
> > > > +       clk_disable_unprepare(tmdev->mod_clk);
> > > >  bus_disable:
> > > >         clk_disable_unprepare(tmdev->bus_clk);
> > > >  assert_reset:
> > > > @@ -395,6 +409,7 @@ static int sun8i_ths_remove(struct platform_device *pdev)
> > > >  {
> > > >         struct ths_device *tmdev = platform_get_drvdata(pdev);
> > > >
> > > > +       clk_disable_unprepare(tmdev->mod_clk);
> > > >         clk_disable_unprepare(tmdev->bus_clk);
> > > >         reset_control_assert(tmdev->reset);
> > > >
> > > > --
> > > > 2.17.1
> > > >
> > > >
> > > > _______________________________________________
> > > > linux-arm-kernel mailing list
> > > > linux-arm-kernel@lists.infradead.org
> > > > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 08/18] thermal: sun8i: support mod clocks
  2019-08-13 20:06         ` Ondřej Jirman
@ 2019-08-14  3:01           ` Vasily Khoruzhick
  2019-08-25 16:14             ` Frank Lee
  0 siblings, 1 reply; 43+ messages in thread
From: Vasily Khoruzhick @ 2019-08-14  3:01 UTC (permalink / raw)
  To: Vasily Khoruzhick, Frank Lee, Mark Rutland, devicetree, Linux PM,
	Maxime Ripard, Greg Kroah-Hartman, Daniel Lezcano, linux-kernel,
	Eduardo Valentin, Chen-Yu Tsai, Rob Herring, Jonathan.Cameron,
	Mauro Carvalho Chehab, rui.zhang, David S. Miller, arm-linux

On Tue, Aug 13, 2019 at 1:06 PM Ondřej Jirman <megous@megous.com> wrote:
>
> On Mon, Aug 12, 2019 at 04:54:15PM -0700, Vasily Khoruzhick wrote:
> > On Mon, Aug 12, 2019 at 4:46 PM Frank Lee <tiny.windzz@gmail.com> wrote:
> > >
> > > HI Vasily,
> > >
> > > On Sat, Aug 10, 2019 at 2:17 PM Vasily Khoruzhick <anarsoul@gmail.com> wrote:
> > > >
> > > > On Fri, Aug 9, 2019 at 10:31 PM Yangtao Li <tiny.windzz@gmail.com> wrote:
> > > > >
> > > > > H3 has extra clock, so introduce something in ths_thermal_chip/ths_device
> > > > > and adds the process of the clock.
> > > > >
> > > > > This is pre-work for supprt it.
> > > > >
> > > > > Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> > > > > ---
> > > > >  drivers/thermal/sun8i_thermal.c | 17 ++++++++++++++++-
> > > > >  1 file changed, 16 insertions(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
> > > > > index b934bc81eba7..6f4294c2aba7 100644
> > > > > --- a/drivers/thermal/sun8i_thermal.c
> > > > > +++ b/drivers/thermal/sun8i_thermal.c
> > > > > @@ -54,6 +54,7 @@ struct tsensor {
> > > > >  };
> > > > >
> > > > >  struct ths_thermal_chip {
> > > > > +       bool            has_mod_clk;
> > > > >         int             sensor_num;
> > > > >         int             offset;
> > > > >         int             scale;
> > > > > @@ -69,6 +70,7 @@ struct ths_device {
> > > > >         struct regmap                           *regmap;
> > > > >         struct reset_control                    *reset;
> > > > >         struct clk                              *bus_clk;
> > > > > +       struct clk                              *mod_clk;
> > > > >         struct tsensor                          sensor[MAX_SENSOR_NUM];
> > > > >  };
> > > > >
> > > > > @@ -274,6 +276,12 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
> > > > >         if (IS_ERR(tmdev->bus_clk))
> > > > >                 return PTR_ERR(tmdev->bus_clk);
> > > > >
> > > > > +       if (tmdev->chip->has_mod_clk) {
> > > > > +               tmdev->mod_clk = devm_clk_get(&pdev->dev, "mod");
> > > > > +               if (IS_ERR(tmdev->mod_clk))
> > > > > +                       return PTR_ERR(tmdev->mod_clk);
> > > > > +       }
> > > > > +
> > > > >         ret = reset_control_deassert(tmdev->reset);
> > > > >         if (ret)
> > > > >                 return ret;
> > > > > @@ -282,12 +290,18 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
> > > > >         if (ret)
> > > > >                 goto assert_reset;
> > > > >
> > > > > -       ret = sun50i_ths_calibrate(tmdev);
> > > > > +       ret = clk_prepare_enable(tmdev->mod_clk);
> > > >
> > > > You have to set rate of modclk before enabling it since you can't rely
> > > > on whatever bootloader left for you.
> > > >
> > > > Also I found that parameters you're using for PC_TEMP_PERIOD, ACQ0 and
> > > > ACQ1 are too aggressive and may result in high interrupt rate to the
> > > > point when it may stall RCU. I changed driver a bit to use params from
> > > > Philipp Rossak's work (modclk set to 4MHz, PC_TEMP_PERIOD is 7, ACQ0
> > > > is 255, ACQ1 is 63) and it fixed RCU stalls for me, see [1] for
> > > > details.
> > >
> > > Why is the RCU stall happening, is it caused by a deadlock?
> > > Can you provide log information and your configuration?
> > > I am a bit curious.
> >
> > It's not deadlock, I believe it just can't handle that many interrupts
> > when running at lowest CPU frequency. Even with Philipp's settings
> > there's ~20 interrupts a second from ths. I don't remember how many
> > interrupts were there with your settings.
> >
> > Unfortunately there's nothing interesting in backtraces, I'm using
> > Pine64-LTS board.
>
> Recently there was a similar issue, with buggy CCU driver that caused
> CIR interrupts being fired constantly, and it also resulted in RCU
> stalls. Looks like a comon cause of RCU stalls.
>
> THS timing settings probably need to be made specific to the SoC, because
> I noticed that the same settings lead to wildly different timings on
> different SoCs.
>
> It would be good to measure how often ths interrupt fires with this driver
> on various SoCs.
>
> 20 times a second and more sounds like overkill. I'd expect a useful
> range to be at most 5-10 times a second. That should be enough to stop
> overheating the SoC due to suddenly increased load, even without a
> heatsink.

Note that A64 has 3 sensors and each sensor has individual interrupt,
so technically it's 6-7 interrupts per sensor per second

> regards,
>         o.
>
> > > Thx,
> > > Yangtao
> > >
> > > >
> > > > [1] https://github.com/anarsoul/linux-2.6/commit/46b8bb0fe2ccd1cd88fa9181a2ecbf79e8d513b2
> > > >
> > > >
> > > > >         if (ret)
> > > > >                 goto bus_disable;
> > > > >
> > > > > +       ret = sun50i_ths_calibrate(tmdev);
> > > > > +       if (ret)
> > > > > +               goto mod_disable;
> > > > > +
> > > > >         return 0;
> > > > >
> > > > > +mod_disable:
> > > > > +       clk_disable_unprepare(tmdev->mod_clk);
> > > > >  bus_disable:
> > > > >         clk_disable_unprepare(tmdev->bus_clk);
> > > > >  assert_reset:
> > > > > @@ -395,6 +409,7 @@ static int sun8i_ths_remove(struct platform_device *pdev)
> > > > >  {
> > > > >         struct ths_device *tmdev = platform_get_drvdata(pdev);
> > > > >
> > > > > +       clk_disable_unprepare(tmdev->mod_clk);
> > > > >         clk_disable_unprepare(tmdev->bus_clk);
> > > > >         reset_control_assert(tmdev->reset);
> > > > >
> > > > > --
> > > > > 2.17.1
> > > > >
> > > > >
> > > > > _______________________________________________
> > > > > linux-arm-kernel mailing list
> > > > > linux-arm-kernel@lists.infradead.org
> > > > > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 02/18] dt-bindings: thermal: add binding document for h6 thermal controller
  2019-08-12 23:40     ` Frank Lee
@ 2019-08-16  9:47       ` Maxime Ripard
  0 siblings, 0 replies; 43+ messages in thread
From: Maxime Ripard @ 2019-08-16  9:47 UTC (permalink / raw)
  To: Frank Lee
  Cc: rui.zhang, Eduardo Valentin, Daniel Lezcano, Rob Herring,
	Mark Rutland, Chen-Yu Tsai, Mauro Carvalho Chehab, David Miller,
	Greg Kroah-Hartman, Jonathan.Cameron, Nicolas Ferre, Linux PM,
	devicetree, Linux ARM, Linux Kernel Mailing List

[-- Attachment #1: Type: text/plain, Size: 3885 bytes --]

On Tue, Aug 13, 2019 at 07:40:44AM +0800, Frank Lee wrote:
> On Mon, Aug 12, 2019 at 4:56 PM Maxime Ripard <maxime.ripard@bootlin.com> wrote:
> >
> > On Sat, Aug 10, 2019 at 05:28:13AM +0000, Yangtao Li wrote:
> > > This patch adds binding document for allwinner h6 thermal controller.
> > >
> > > Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> > > ---
> > >  .../bindings/thermal/sun8i-thermal.yaml       | 79 +++++++++++++++++++
> > >  1 file changed, 79 insertions(+)
> > >  create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
> > >
> > > diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
> > > new file mode 100644
> > > index 000000000000..e0973199ba3c
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
> >
> > We've used so far for the schemas the first compatible to introduce
> > that controller as the filename, we should be consistent here. In that
> > case that would be allwinner,sun8i-a23-ths.yaml
> >
> > > @@ -0,0 +1,79 @@
> > > +# SPDX-License-Identifier: GPL-2.0
> > > +%YAML 1.2
> > > +---
> > > +$id: http://devicetree.org/schemas/thermal/sun8i-thermal.yaml#
> > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > +
> > > +title: Allwinner SUN8I Thermal Controller Device Tree Bindings
> > > +
> > > +maintainers:
> > > +  - Yangtao Li <tiny.windzz@gmail.com>
> > > +
> > > +description: |-
> > > +  This describes the device tree binding for the Allwinner thermal
> > > +  controller which measures the on-SoC temperatures.
> > > +
> > > +properties:
> > > +  compatible:
> > > +    enum:
> > > +      - allwinner,sun50i-h6-ths
> > > +
> > > +  reg:
> > > +    maxItems: 1
> > > +
> > > +  interrupts:
> > > +    maxItems: 1
> > > +
> > > +  resets:
> > > +    maxItems: 1
> > > +
> > > +  clocks:
> > > +    maxItems: 1
> > > +
> > > +  clock-names:
> > > +    const: bus
> > > +
> > > +  "#thermal-sensor-cells":
> > > +    const: 1
> > > +
> > > +  nvmem-cells:
> >
> > You need a maxItems here too
> >
> > > +    description: ths calibrate data
> >
> > What about something like this:
> >
> > Calibration data for the thermal sensor
> >
> > > +
> > > +  nvmem-cell-names:
> > > +    const: calib
> >
> > I'm not sure we need a abbreviation here, calibration would be more
> > explicit
> >
> > > +
> > > +required:
> > > +  - compatible
> > > +  - reg
> > > +  - reset
> > > +  - clocks
> > > +  - clock-names
> > > +  - interrupts
> > > +  - "#thermal-sensor-cells"
> > > +
> > > +additionalProperties: false
> > > +
> > > +examples:
> > > +  - |
> > > +    ths: ths@5070400 {
> > > +        compatible = "allwinner,sun50i-h6-ths";
> > > +        reg = <0x05070400 0x100>;
> > > +        clocks = <&ccu CLK_BUS_THS>;
> > > +        clock-names = "bus";
> > > +        resets = <&ccu RST_BUS_THS>;
> > > +        interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
> >
> > Those examples won't compile.
>
> Emmm, I have some questions about this.
> I added this information and it can be compiled.

With your patch applied,

$ ARCH=arm DT_SCHEMA_FILES=Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml make -j4 dt_binding_check
  CHKDT   Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
  DTC     Documentation/devicetree/bindings/thermal/sun8i-thermal.example.dt.yaml
Error: Documentation/devicetree/bindings/thermal/sun8i-thermal.example.dts:20.28-29 syntax error
FATAL ERROR: Unable to parse input tree
make[2]: *** [scripts/Makefile.lib:299: Documentation/devicetree/bindings/thermal/sun8i-thermal.example.dt.yaml] Error 1
make[1]: *** [/home/max/Work/src/linux/Makefile:1286: dt_binding_check] Error 2
make: *** [/home/max/Work/src/linux/Makefile:179: sub-make] Error 2

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 08/18] thermal: sun8i: support mod clocks
  2019-08-14  3:01           ` Vasily Khoruzhick
@ 2019-08-25 16:14             ` Frank Lee
  2019-10-21  3:41               ` Vasily Khoruzhick
  0 siblings, 1 reply; 43+ messages in thread
From: Frank Lee @ 2019-08-25 16:14 UTC (permalink / raw)
  To: Vasily Khoruzhick
  Cc: Mark Rutland, devicetree, Linux PM, Maxime Ripard,
	Greg Kroah-Hartman, Daniel Lezcano, linux-kernel,
	Eduardo Valentin, Chen-Yu Tsai, Rob Herring, Jonathan.Cameron,
	Mauro Carvalho Chehab, rui.zhang, David S. Miller, arm-linux

HI Vasily,

On Wed, Aug 14, 2019 at 11:01 AM Vasily Khoruzhick <anarsoul@gmail.com> wrote:
>
> On Tue, Aug 13, 2019 at 1:06 PM Ondřej Jirman <megous@megous.com> wrote:
> >
> > On Mon, Aug 12, 2019 at 04:54:15PM -0700, Vasily Khoruzhick wrote:
> > > On Mon, Aug 12, 2019 at 4:46 PM Frank Lee <tiny.windzz@gmail.com> wrote:
> > > >
> > > > HI Vasily,
> > > >
> > > > On Sat, Aug 10, 2019 at 2:17 PM Vasily Khoruzhick <anarsoul@gmail.com> wrote:
> > > > >
> > > > > On Fri, Aug 9, 2019 at 10:31 PM Yangtao Li <tiny.windzz@gmail.com> wrote:
> > > > > >
> > > > > > H3 has extra clock, so introduce something in ths_thermal_chip/ths_device
> > > > > > and adds the process of the clock.
> > > > > >
> > > > > > This is pre-work for supprt it.
> > > > > >
> > > > > > Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> > > > > > ---
> > > > > >  drivers/thermal/sun8i_thermal.c | 17 ++++++++++++++++-
> > > > > >  1 file changed, 16 insertions(+), 1 deletion(-)
> > > > > >
> > > > > > diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
> > > > > > index b934bc81eba7..6f4294c2aba7 100644
> > > > > > --- a/drivers/thermal/sun8i_thermal.c
> > > > > > +++ b/drivers/thermal/sun8i_thermal.c
> > > > > > @@ -54,6 +54,7 @@ struct tsensor {
> > > > > >  };
> > > > > >
> > > > > >  struct ths_thermal_chip {
> > > > > > +       bool            has_mod_clk;
> > > > > >         int             sensor_num;
> > > > > >         int             offset;
> > > > > >         int             scale;
> > > > > > @@ -69,6 +70,7 @@ struct ths_device {
> > > > > >         struct regmap                           *regmap;
> > > > > >         struct reset_control                    *reset;
> > > > > >         struct clk                              *bus_clk;
> > > > > > +       struct clk                              *mod_clk;
> > > > > >         struct tsensor                          sensor[MAX_SENSOR_NUM];
> > > > > >  };
> > > > > >
> > > > > > @@ -274,6 +276,12 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
> > > > > >         if (IS_ERR(tmdev->bus_clk))
> > > > > >                 return PTR_ERR(tmdev->bus_clk);
> > > > > >
> > > > > > +       if (tmdev->chip->has_mod_clk) {
> > > > > > +               tmdev->mod_clk = devm_clk_get(&pdev->dev, "mod");
> > > > > > +               if (IS_ERR(tmdev->mod_clk))
> > > > > > +                       return PTR_ERR(tmdev->mod_clk);
> > > > > > +       }
> > > > > > +
> > > > > >         ret = reset_control_deassert(tmdev->reset);
> > > > > >         if (ret)
> > > > > >                 return ret;
> > > > > > @@ -282,12 +290,18 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
> > > > > >         if (ret)
> > > > > >                 goto assert_reset;
> > > > > >
> > > > > > -       ret = sun50i_ths_calibrate(tmdev);
> > > > > > +       ret = clk_prepare_enable(tmdev->mod_clk);
> > > > >
> > > > > You have to set rate of modclk before enabling it since you can't rely
> > > > > on whatever bootloader left for you.
> > > > >
> > > > > Also I found that parameters you're using for PC_TEMP_PERIOD, ACQ0 and
> > > > > ACQ1 are too aggressive and may result in high interrupt rate to the
> > > > > point when it may stall RCU. I changed driver a bit to use params from
> > > > > Philipp Rossak's work (modclk set to 4MHz, PC_TEMP_PERIOD is 7, ACQ0
> > > > > is 255, ACQ1 is 63) and it fixed RCU stalls for me, see [1] for
> > > > > details.
> > > >
> > > > Why is the RCU stall happening, is it caused by a deadlock?
> > > > Can you provide log information and your configuration?
> > > > I am a bit curious.
> > >
> > > It's not deadlock, I believe it just can't handle that many interrupts
> > > when running at lowest CPU frequency. Even with Philipp's settings
> > > there's ~20 interrupts a second from ths. I don't remember how many
> > > interrupts were there with your settings.
> > >
> > > Unfortunately there's nothing interesting in backtraces, I'm using
> > > Pine64-LTS board.
> >
> > Recently there was a similar issue, with buggy CCU driver that caused
> > CIR interrupts being fired constantly, and it also resulted in RCU
> > stalls. Looks like a comon cause of RCU stalls.
> >
> > THS timing settings probably need to be made specific to the SoC, because
> > I noticed that the same settings lead to wildly different timings on
> > different SoCs.
> >
> > It would be good to measure how often ths interrupt fires with this driver
> > on various SoCs.
> >
> > 20 times a second and more sounds like overkill. I'd expect a useful
> > range to be at most 5-10 times a second. That should be enough to stop
> > overheating the SoC due to suddenly increased load, even without a
> > heatsink.
>
> Note that A64 has 3 sensors and each sensor has individual interrupt,
> so technically it's 6-7 interrupts per sensor per second

You only need to increase the value of the period to reduce the number
of interrupts.
Can you test the relationship between the period and the number of interrupts
when the mod clock does not change and stays 24M?

Thx.
Yangtao

>
> > regards,
> >         o.
> >
> > > > Thx,
> > > > Yangtao
> > > >
> > > > >
> > > > > [1] https://github.com/anarsoul/linux-2.6/commit/46b8bb0fe2ccd1cd88fa9181a2ecbf79e8d513b2
> > > > >
> > > > >
> > > > > >         if (ret)
> > > > > >                 goto bus_disable;
> > > > > >
> > > > > > +       ret = sun50i_ths_calibrate(tmdev);
> > > > > > +       if (ret)
> > > > > > +               goto mod_disable;
> > > > > > +
> > > > > >         return 0;
> > > > > >
> > > > > > +mod_disable:
> > > > > > +       clk_disable_unprepare(tmdev->mod_clk);
> > > > > >  bus_disable:
> > > > > >         clk_disable_unprepare(tmdev->bus_clk);
> > > > > >  assert_reset:
> > > > > > @@ -395,6 +409,7 @@ static int sun8i_ths_remove(struct platform_device *pdev)
> > > > > >  {
> > > > > >         struct ths_device *tmdev = platform_get_drvdata(pdev);
> > > > > >
> > > > > > +       clk_disable_unprepare(tmdev->mod_clk);
> > > > > >         clk_disable_unprepare(tmdev->bus_clk);
> > > > > >         reset_control_assert(tmdev->reset);
> > > > > >
> > > > > > --
> > > > > > 2.17.1
> > > > > >
> > > > > >
> > > > > > _______________________________________________
> > > > > > linux-arm-kernel mailing list
> > > > > > linux-arm-kernel@lists.infradead.org
> > > > > > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> > >
> > > _______________________________________________
> > > linux-arm-kernel mailing list
> > > linux-arm-kernel@lists.infradead.org
> > > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 10/18] dt-bindings: thermal: add binding document for h3 thermal controller
  2019-08-10  5:28 ` [PATCH v5 10/18] dt-bindings: thermal: add binding document for h3 thermal controller Yangtao Li
@ 2019-08-27 15:26   ` Rob Herring
  0 siblings, 0 replies; 43+ messages in thread
From: Rob Herring @ 2019-08-27 15:26 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre, linux-pm, devicetree,
	linux-arm-kernel, linux-kernel, Yangtao Li

On Sat, 10 Aug 2019 05:28:21 +0000, Yangtao Li wrote:
> This patch adds binding document for allwinner h3 thermal controller.
> 
> Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> ---
>  .../bindings/thermal/sun8i-thermal.yaml       | 81 ++++++++++++++++++-
>  1 file changed, 78 insertions(+), 3 deletions(-)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 12/18] dt-bindings: thermal: add binding document for a64 thermal controller
  2019-08-10  5:28 ` [PATCH v5 12/18] dt-bindings: thermal: add binding document for a64 thermal controller Yangtao Li
@ 2019-08-27 15:26   ` Rob Herring
  0 siblings, 0 replies; 43+ messages in thread
From: Rob Herring @ 2019-08-27 15:26 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre, linux-pm, devicetree,
	linux-arm-kernel, linux-kernel, Yangtao Li

On Sat, 10 Aug 2019 05:28:23 +0000, Yangtao Li wrote:
> This patch adds binding document for allwinner a64 thermal controller.
> 
> Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> ---
>  Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 14/18] dt-bindings: thermal: add binding document for h5 thermal controller
  2019-08-10  5:28 ` [PATCH v5 14/18] dt-bindings: thermal: add binding document for h5 thermal controller Yangtao Li
@ 2019-08-27 15:27   ` Rob Herring
  0 siblings, 0 replies; 43+ messages in thread
From: Rob Herring @ 2019-08-27 15:27 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre, linux-pm, devicetree,
	linux-arm-kernel, linux-kernel, Yangtao Li

On Sat, 10 Aug 2019 05:28:25 +0000, Yangtao Li wrote:
> This patch adds binding document for allwinner h5 thermal controller.
> 
> Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> ---
>  Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 17/18] dt-bindings: thermal: add binding document for r40 thermal controller
  2019-08-10  5:28 ` [PATCH v5 17/18] dt-bindings: thermal: add binding document for r40 thermal controller Yangtao Li
@ 2019-08-27 15:27   ` Rob Herring
  0 siblings, 0 replies; 43+ messages in thread
From: Rob Herring @ 2019-08-27 15:27 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre, linux-pm, devicetree,
	linux-arm-kernel, linux-kernel, Yangtao Li

On Sat, 10 Aug 2019 05:28:28 +0000, Yangtao Li wrote:
> This patch adds binding document for allwinner r40 thermal controller.
> 
> Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> ---
>  Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 03/18] thermal: fix indentation in makefile
  2019-08-10  5:28 ` [PATCH v5 03/18] thermal: fix indentation in makefile Yangtao Li
@ 2019-08-28 12:40   ` Zhang Rui
  0 siblings, 0 replies; 43+ messages in thread
From: Zhang Rui @ 2019-08-28 12:40 UTC (permalink / raw)
  To: Yangtao Li, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel

On Sat, 2019-08-10 at 05:28 +0000, Yangtao Li wrote:
> To unify code style.
> 
> Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>

the later patches in this series does not change Makefile.
So this seems to be a cleanup patch independent of this patch set.
It's better to remove this patch from this patch series.

thanks,
rui
> ---
>  drivers/thermal/Makefile | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index fa6f8b206281..d7eafb5ef8ef 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -5,7 +5,7 @@
>  
>  obj-$(CONFIG_THERMAL)		+= thermal_sys.o
>  thermal_sys-y			+= thermal_core.o
> thermal_sysfs.o \
> -					thermal_helpers.o
> +				   thermal_helpers.o
>  
>  # interface to/from other layers providing sensors
>  thermal_sys-$(CONFIG_THERMAL_HWMON)		+= thermal_hwmon.o
> @@ -25,11 +25,11 @@ thermal_sys-$(CONFIG_CPU_THERMAL)	+=
> cpu_cooling.o
>  thermal_sys-$(CONFIG_CLOCK_THERMAL)	+= clock_cooling.o
>  
>  # devfreq cooling
> -thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
> +thermal_sys-$(CONFIG_DEVFREQ_THERMAL) 	+= devfreq_cooling.o
>  
>  # platform thermal drivers
>  obj-y				+= broadcom/
> -obj-$(CONFIG_THERMAL_MMIO)		+= thermal_mmio.o
> +obj-$(CONFIG_THERMAL_MMIO)	+= thermal_mmio.o
>  obj-$(CONFIG_SPEAR_THERMAL)	+= spear_thermal.o
>  obj-$(CONFIG_SUN8I_THERMAL)     += sun8i_thermal.o
>  obj-$(CONFIG_ROCKCHIP_THERMAL)	+= rockchip_thermal.o
> @@ -50,7 +50,7 @@ obj-$(CONFIG_TI_SOC_THERMAL)	+= ti-soc-
> thermal/
>  obj-y				+= st/
>  obj-$(CONFIG_QCOM_TSENS)	+= qcom/
>  obj-y				+= tegra/
> -obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
> +obj-$(CONFIG_HISI_THERMAL)     	+= hisi_thermal.o
>  obj-$(CONFIG_MTK_THERMAL)	+= mtk_thermal.o
>  obj-$(CONFIG_GENERIC_ADC_THERMAL)	+= thermal-generic-adc.o
>  obj-$(CONFIG_ZX2967_THERMAL)	+= zx2967_thermal.o


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 09/18] thermal: sun8i: rework for ths calibrate func
  2019-08-10  5:28 ` [PATCH v5 09/18] thermal: sun8i: rework for ths calibrate func Yangtao Li
@ 2019-08-28 12:45   ` Zhang Rui
  0 siblings, 0 replies; 43+ messages in thread
From: Zhang Rui @ 2019-08-28 12:45 UTC (permalink / raw)
  To: Yangtao Li, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel

On Sat, 2019-08-10 at 05:28 +0000, Yangtao Li wrote:
> Here, we do something to prepare for the subsequent
> support of multiple platforms.
> 
> 1) rename sun50i_ths_calibrate to sun8i_ths_calibrate, because
>    this function should be suitable for all platforms now.
> 
> 2) introduce calibrate callback to mask calibration method
>    differences.
> 
> Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>

IMO, patch 4/18 to patch 9/18 are all changes to a new file introduced
in patch 1/18, so why not have a prettier patch 1/18 instead of
separate patches?

thanks,
rui

> ---
>  drivers/thermal/sun8i_thermal.c | 86 ++++++++++++++++++-------------
> --
>  1 file changed, 48 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/thermal/sun8i_thermal.c
> b/drivers/thermal/sun8i_thermal.c
> index 6f4294c2aba7..47c20c4c69e7 100644
> --- a/drivers/thermal/sun8i_thermal.c
> +++ b/drivers/thermal/sun8i_thermal.c
> @@ -60,6 +60,8 @@ struct ths_thermal_chip {
>  	int		scale;
>  	int		ft_deviation;
>  	int		temp_data_base;
> +	int		(*calibrate)(struct ths_device *tmdev,
> +				     u16 *caldata, int callen);
>  	int		(*init)(struct ths_device *tmdev);
>  	int             (*irq_ack)(struct ths_device *tmdev);
>  };
> @@ -152,45 +154,14 @@ static irqreturn_t sun8i_irq_thread(int irq,
> void *data)
>  	return IRQ_HANDLED;
>  }
>  
> -static int sun50i_ths_calibrate(struct ths_device *tmdev)
> +static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
> +				   u16 *caldata, int callen)
>  {
> -	struct nvmem_cell *calcell;
>  	struct device *dev = tmdev->dev;
> -	u16 *caldata;
> -	size_t callen;
> -	int ft_temp;
> -	int i, ret = 0;
> -
> -	calcell = devm_nvmem_cell_get(dev, "calib");
> -	if (IS_ERR(calcell)) {
> -		if (PTR_ERR(calcell) == -EPROBE_DEFER)
> -			return -EPROBE_DEFER;
> -		/*
> -		 * Even if the external calibration data stored in sid
> is
> -		 * not accessible, the THS hardware can still work,
> although
> -		 * the data won't be so accurate.
> -		 *
> -		 * The default value of calibration register is 0x800
> for
> -		 * every sensor, and the calibration value is usually
> 0x7xx
> -		 * or 0x8xx, so they won't be away from the default
> value
> -		 * for a lot.
> -		 *
> -		 * So here we do not return error if the calibartion
> data is
> -		 * not available, except the probe needs deferring.
> -		 */
> -		goto out;
> -	}
> +	int i, ft_temp;
>  
> -	caldata = nvmem_cell_read(calcell, &callen);
> -	if (IS_ERR(caldata)) {
> -		ret = PTR_ERR(caldata);
> -		goto out;
> -	}
> -
> -	if (!caldata[0] || callen < 2 + 2 * tmdev->chip->sensor_num) {
> -		ret = -EINVAL;
> -		goto out_free;
> -	}
> +	if (!caldata[0] || callen < 2 + 2 * tmdev->chip->sensor_num)
> +		return -EINVAL;
>  
>  	/*
>  	 * efuse layout:
> @@ -245,7 +216,45 @@ static int sun50i_ths_calibrate(struct
> ths_device *tmdev)
>  				   cdata << offset);
>  	}
>  
> -out_free:
> +	return 0;
> +}
> +
> +static int sun8i_ths_calibrate(struct ths_device *tmdev)
> +{
> +	struct nvmem_cell *calcell;
> +	struct device *dev = tmdev->dev;
> +	u16 *caldata;
> +	size_t callen;
> +	int ret = 0;
> +
> +	calcell = devm_nvmem_cell_get(dev, "calib");
> +	if (IS_ERR(calcell)) {
> +		if (PTR_ERR(calcell) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +		/*
> +		 * Even if the external calibration data stored in sid
> is
> +		 * not accessible, the THS hardware can still work,
> although
> +		 * the data won't be so accurate.
> +		 *
> +		 * The default value of calibration register is 0x800
> for
> +		 * every sensor, and the calibration value is usually
> 0x7xx
> +		 * or 0x8xx, so they won't be away from the default
> value
> +		 * for a lot.
> +		 *
> +		 * So here we do not return error if the calibartion
> data is
> +		 * not available, except the probe needs deferring.
> +		 */
> +		goto out;
> +	}
> +
> +	caldata = nvmem_cell_read(calcell, &callen);
> +	if (IS_ERR(caldata)) {
> +		ret = PTR_ERR(caldata);
> +		goto out;
> +	}
> +
> +	tmdev->chip->calibrate(tmdev, caldata, callen);
> +
>  	kfree(caldata);
>  out:
>  	return ret;
> @@ -294,7 +303,7 @@ static int sun8i_ths_resource_init(struct
> ths_device *tmdev)
>  	if (ret)
>  		goto bus_disable;
>  
> -	ret = sun50i_ths_calibrate(tmdev);
> +	ret = sun8i_ths_calibrate(tmdev);
>  	if (ret)
>  		goto mod_disable;
>  
> @@ -422,6 +431,7 @@ static const struct ths_thermal_chip
> sun50i_h6_ths = {
>  	.scale = -67,
>  	.ft_deviation = SUN50I_H6_FT_DEVIATION,
>  	.temp_data_base = SUN50I_H6_THS_TEMP_DATA,
> +	.calibrate = sun50i_h6_ths_calibrate,
>  	.init = sun50i_h6_thermal_init,
>  	.irq_ack = sun50i_h6_irq_ack,
>  };


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 01/18] thermal: sun8i: add thermal driver for h6
  2019-08-10  5:28 ` [PATCH v5 01/18] thermal: sun8i: " Yangtao Li
@ 2019-09-01  2:06   ` Ondřej Jirman
  2019-09-01 21:04   ` Ondřej Jirman
  1 sibling, 0 replies; 43+ messages in thread
From: Ondřej Jirman @ 2019-09-01  2:06 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre, devicetree, linux-kernel,
	linux-arm-kernel, linux-pm

Hello Yangtao,

On Sat, Aug 10, 2019 at 05:28:12AM +0000, Yangtao Li wrote:
> This patch adds the support for allwinner thermal sensor, within
> allwinner SoC. It will register sensors for thermal framework
> and use device tree to bind cooling device.
> 
> Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> ---
>  MAINTAINERS                     |   7 +
>  drivers/thermal/Kconfig         |  14 ++
>  drivers/thermal/Makefile        |   1 +
>  drivers/thermal/sun8i_thermal.c | 399 ++++++++++++++++++++++++++++++++
>  4 files changed, 421 insertions(+)
>  create mode 100644 drivers/thermal/sun8i_thermal.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 47800d32cfbc..89dc43f4064d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -682,6 +682,13 @@ L:	linux-crypto@vger.kernel.org
>  S:	Maintained
>  F:	drivers/crypto/sunxi-ss/
>  
> +ALLWINNER THERMAL DRIVER
> +M:	Yangtao Li <tiny.windzz@gmail.com>
> +L:	linux-pm@vger.kernel.org
> +S:	Maintained
> +F:	Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
> +F:	drivers/thermal/sun8i_thermal.c
> +
>  ALLWINNER VPU DRIVER
>  M:	Maxime Ripard <maxime.ripard@bootlin.com>
>  M:	Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 9966364a6deb..f8b73b32b92d 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -262,6 +262,20 @@ config SPEAR_THERMAL
>  	  Enable this to plug the SPEAr thermal sensor driver into the Linux
>  	  thermal framework.
>  
> +config SUN8I_THERMAL
> +	tristate "Allwinner sun8i thermal driver"
> +	depends on ARCH_SUNXI || COMPILE_TEST
> +	depends on HAS_IOMEM
> +	depends on NVMEM
> +	depends on OF
> +	depends on RESET_CONTROLLER
> +	help
> +	  Support for the sun8i thermal sensor driver into the Linux thermal
> +	  framework.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called sun8i-thermal.
> +
>  config ROCKCHIP_THERMAL
>  	tristate "Rockchip thermal driver"
>  	depends on ARCH_ROCKCHIP || COMPILE_TEST
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 74a37c7f847a..fa6f8b206281 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -31,6 +31,7 @@ thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
>  obj-y				+= broadcom/
>  obj-$(CONFIG_THERMAL_MMIO)		+= thermal_mmio.o
>  obj-$(CONFIG_SPEAR_THERMAL)	+= spear_thermal.o
> +obj-$(CONFIG_SUN8I_THERMAL)     += sun8i_thermal.o
>  obj-$(CONFIG_ROCKCHIP_THERMAL)	+= rockchip_thermal.o
>  obj-$(CONFIG_RCAR_THERMAL)	+= rcar_thermal.o
>  obj-$(CONFIG_RCAR_GEN3_THERMAL)	+= rcar_gen3_thermal.o
> diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
> new file mode 100644
> index 000000000000..2ce36fa3fec3
> --- /dev/null
> +++ b/drivers/thermal/sun8i_thermal.c
> @@ -0,0 +1,399 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Thermal sensor driver for Allwinner SOC
> + * Copyright (C) 2019 Yangtao Li
> + *
> + * Based on the work of Icenowy Zheng <icenowy@aosc.io>
> + * Based on the work of Ondrej Jirman <megous@megous.com>
> + * Based on the work of Josef Gajdusek <atx@atx.name>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/nvmem-consumer.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +#include <linux/slab.h>
> +#include <linux/thermal.h>
> +
> +#define MAX_SENSOR_NUM	4
> +
> +#define SUN50I_H6_SENSOR_NUM	2
> +#define SUN50I_H6_OFFSET	-2794
> +#define SUN50I_H6_SCALE		-67
> +
> +#define FT_TEMP_MASK				GENMASK(11, 0)
> +#define TEMP_CALIB_MASK				GENMASK(11, 0)
> +#define TEMP_TO_REG				672
> +#define CALIBRATE_DEFAULT			0x800
> +
> +#define SUN50I_THS_CTRL0			0x00
> +#define SUN50I_H6_THS_ENABLE			0x04
> +#define SUN50I_H6_THS_PC			0x08
> +#define SUN50I_H6_THS_DIC			0x10
> +#define SUN50I_H6_THS_DIS			0x20
> +#define SUN50I_H6_THS_MFC			0x30
> +#define SUN50I_H6_THS_TEMP_CALIB		0xa0
> +#define SUN50I_H6_THS_TEMP_DATA			0xc0
> +
> +#define SUN50I_THS_CTRL0_T_ACQ(x)		((GENMASK(15, 0) & (x)) << 16)
> +#define SUN50I_THS_FILTER_EN			BIT(2)
> +#define SUN50I_THS_FILTER_TYPE(x)		(GENMASK(1, 0) & (x))
> +#define SUN50I_H6_THS_PC_TEMP_PERIOD(x)		((GENMASK(19, 0) & (x)) << 12)
> +#define SUN50I_H6_THS_DATA_IRQ_STS(x)		BIT(x)
> +
> +/* millidegree celsius */
> +#define SUN50I_H6_FT_DEVIATION			7000
> +
> +struct ths_device;
> +
> +struct tsensor {
> +	struct ths_device		*tmdev;
> +	struct thermal_zone_device	*tzd;
> +	int				id;
> +};
> +
> +struct ths_device {
> +	struct device				*dev;
> +	struct regmap				*regmap;
> +	struct reset_control			*reset;
> +	struct clk				*bus_clk;
> +	struct tsensor				sensor[MAX_SENSOR_NUM];
> +};
> +
> +/* Temp Unit: millidegree Celsius */
> +static int sun8i_ths_reg2temp(struct ths_device *tmdev,
> +			      int reg)
> +{
> +	return (reg + SUN50I_H6_OFFSET) * SUN50I_H6_SCALE;
> +}
> +
> +static int sun8i_ths_get_temp(void *data, int *temp)
> +{
> +	struct tsensor *s = data;
> +	struct ths_device *tmdev = s->tmdev;
> +	int val;
> +
> +	regmap_read(tmdev->regmap, SUN50I_H6_THS_TEMP_DATA +
> +		    0x4 * s->id, &val);
> +
> +	/* ths have no data yet */
> +	if (!val)
> +		return -EAGAIN;
> +
> +	*temp = sun8i_ths_reg2temp(tmdev, val);
> +	/*
> +	 * XX - According to the original sdk, there are some platforms(rarely)
> +	 * that add a fixed offset value after calculating the temperature
> +	 * value. We can't simply put it on the formula for calculating the
> +	 * temperature above, because the formula for calculating the
> +	 * temperature above is also used when the sensor is calibrated. If
> +	 * do this, the correct calibration formula is hard to know.
> +	 */
> +	*temp += SUN50I_H6_FT_DEVIATION;
> +
> +	return 0;
> +}
> +
> +static const struct thermal_zone_of_device_ops ths_ops = {
> +	.get_temp = sun8i_ths_get_temp,
> +};
> +
> +static const struct regmap_config config = {
> +	.reg_bits = 32,
> +	.val_bits = 32,
> +	.reg_stride = 4,
> +	.fast_io = true,
> +};
> +
> +static irqreturn_t sun50i_h6_irq_thread(int irq, void *data)
> +{
> +	struct ths_device *tmdev = data;
> +	int i, state;
> +
> +	regmap_read(tmdev->regmap, SUN50I_H6_THS_DIS, &state);
> +
> +	for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
> +
> +		if (state & SUN50I_H6_THS_DATA_IRQ_STS(i)) {
> +			/* clear data irq pending */
> +			regmap_write(tmdev->regmap, SUN50I_H6_THS_DIS,
> +				     SUN50I_H6_THS_DATA_IRQ_STS(i));
> +
> +			thermal_zone_device_update(tmdev->sensor[i].tzd,
> +						   THERMAL_EVENT_UNSPECIFIED);
> +		}
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int sun50i_ths_calibrate(struct ths_device *tmdev)
> +{
> +	struct nvmem_cell *calcell;
> +	struct device *dev = tmdev->dev;
> +	u16 *caldata;
> +	size_t callen;
> +	int ft_temp;
> +	int i, ret = 0;
> +
> +	calcell = devm_nvmem_cell_get(dev, "calib");
> +	if (IS_ERR(calcell)) {
> +		if (PTR_ERR(calcell) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +		/*
> +		 * Even if the external calibration data stored in sid is
> +		 * not accessible, the THS hardware can still work, although
> +		 * the data won't be so accurate.
> +		 *
> +		 * The default value of calibration register is 0x800 for
> +		 * every sensor, and the calibration value is usually 0x7xx
> +		 * or 0x8xx, so they won't be away from the default value
> +		 * for a lot.
> +		 *
> +		 * So here we do not return error if the calibartion data is
> +		 * not available, except the probe needs deferring.
> +		 */
> +		goto out;
> +	}
> +
> +	caldata = nvmem_cell_read(calcell, &callen);
> +	if (IS_ERR(caldata)) {
> +		ret = PTR_ERR(caldata);
> +		goto out;
> +	}
> +
> +	if (!caldata[0] || callen < 2 + 2 * SUN50I_H6_SENSOR_NUM) {
> +		ret = -EINVAL;
> +		goto out_free;
> +	}
> +
> +	/*
> +	 * efuse layout:
> +	 *
> +	 *	0   11  16	 32
> +	 *	+-------+-------+-------+
> +	 *	|temp|  |sensor0|sensor1|
> +	 *	+-------+-------+-------+
> +	 *
> +	 * The calibration data on the H6 is the ambient temperature and
> +	 * sensor values that are filled during the factory test stage.
> +	 *
> +	 * The unit of stored FT temperature is 0.1 degreee celusis.
> +	 * Through the stored ambient temperature and the data read
> +	 * by the sensor, after a certain calculation, the calibration
> +	 * value to be compensated can be obtained.
> +	 */
> +	ft_temp = caldata[0] & FT_TEMP_MASK;
> +
> +	for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
> +		int reg = (int)caldata[i + 1];
> +		int sensor_temp = sun8i_ths_reg2temp(tmdev, reg);
> +		int delta, cdata, offset;
> +
> +		/*
> +		 * To calculate the calibration value:
> +		 *
> +		 * X(in Celsius) = Ts - ft_temp
> +		 * delta = X * 10000 / TEMP_TO_REG
> +		 * cdata = CALIBRATE_DEFAULT - delta
> +		 *
> +		 * cdata: calibration value
> +		 */
> +		delta = (sensor_temp - ft_temp * 100) * 10 / TEMP_TO_REG;
> +		cdata = CALIBRATE_DEFAULT - delta;
> +		if (cdata & ~TEMP_CALIB_MASK) {
> +			/*
> +			 * Calibration value more than 12-bit, but calibration
> +			 * register is 12-bit. In this case, ths hardware can
> +			 * still work without calibration, although the data
> +			 * won't be so accurate.
> +			 */
> +			dev_warn(dev, "sensor%d is not calibrated.\n", i);
> +
> +			continue;
> +		}
> +
> +		offset = (i % 2) << 4;
> +		regmap_update_bits(tmdev->regmap,
> +				   SUN50I_H6_THS_TEMP_CALIB + ((i >> 1) * 4),
> +				   0xfff << offset,
> +				   cdata << offset);
> +	}
> +
> +out_free:
> +	kfree(caldata);
> +out:
> +	return ret;
> +}
> +
> +static int sun8i_ths_resource_init(struct ths_device *tmdev)
> +{
> +	struct device *dev = tmdev->dev;
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct resource *mem;
> +	void __iomem *base;
> +	int ret;
> +
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	base = devm_ioremap_resource(dev, mem);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	tmdev->regmap = devm_regmap_init_mmio(dev, base, &config);
> +	if (IS_ERR(tmdev->regmap))
> +		return PTR_ERR(tmdev->regmap);
> +
> +	tmdev->reset = devm_reset_control_get(dev, 0);
> +	if (IS_ERR(tmdev->reset))
> +		return PTR_ERR(tmdev->reset);
> +
> +	tmdev->bus_clk = devm_clk_get(&pdev->dev, "bus");
> +	if (IS_ERR(tmdev->bus_clk))
> +		return PTR_ERR(tmdev->bus_clk);
> +
> +	ret = reset_control_deassert(tmdev->reset);
> +	if (ret)
> +		return ret;
> +
> +	ret = clk_prepare_enable(tmdev->bus_clk);
> +	if (ret)
> +		goto assert_reset;
> +
> +	ret = sun50i_ths_calibrate(tmdev);
> +	if (ret)
> +		goto bus_disable;
> +
> +	return 0;
> +
> +bus_disable:
> +	clk_disable_unprepare(tmdev->bus_clk);
> +assert_reset:
> +	reset_control_assert(tmdev->reset);
> +
> +	return ret;
> +}
> +
> +static int sun50i_h6_thermal_init(struct ths_device *tmdev)
> +{
> +	int val;
> +
> +	/*
> +	 * clkin = 24MHz
> +	 * T acquire = clkin / (x + 1)
> +	 *           = 20us
> +	 */

I suggest something along the lines of:

        /*                                                                                                                                                                                             
         * T_acq = 20us                                                                                                                                                                                
         * clkin = 24MHz                                                                                                                                                                               
         *                                                                                                                                                                                             
         * x = T_acq * clkin - 1                                                                                                                                                                       
         *   = 479                                                                                                                                                                                     
         */       

Makes it much more clear how the value in SUN50I_THS_CTRL0_T_ACQ was
arrived at and how to calculate a new one.

> +	regmap_write(tmdev->regmap, SUN50I_THS_CTRL0,
> +		     SUN50I_THS_CTRL0_T_ACQ(479));
> +	/* average over 4 samples */
> +	regmap_write(tmdev->regmap, SUN50I_H6_THS_MFC,
> +		     SUN50I_THS_FILTER_EN |
> +		     SUN50I_THS_FILTER_TYPE(1));
> +	/* period = (x + 1) * 4096 / clkin; ~10ms */

As above, here I suggest:

        /*
         * clkin = 24MHz
         * filter_samples = 4
         * period = 0.25s
         *
         * x = period * clkin / 4096 / filter_samples - 1
         *   = 365
         */

Also please change this to 365 from 58. I think 4 readings per second are
enough. Certainly, 25 are a bit too much.

> +	regmap_write(tmdev->regmap, SUN50I_H6_THS_PC,
> +		     SUN50I_H6_THS_PC_TEMP_PERIOD(58));
> +	/* enable sensor */
> +	val = GENMASK(SUN50I_H6_SENSOR_NUM - 1, 0);
> +	regmap_write(tmdev->regmap, SUN50I_H6_THS_ENABLE, val);
> +	/* thermal data interrupt enable */
> +	val = GENMASK(SUN50I_H6_SENSOR_NUM - 1, 0);
> +	regmap_write(tmdev->regmap, SUN50I_H6_THS_DIC, val);
> +
> +	return 0;
> +}
> +
> +static int sun8i_ths_register(struct ths_device *tmdev)
> +{
> +	struct thermal_zone_device *tzd;
> +	int i;
> +
> +	for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
> +		tmdev->sensor[i].tmdev = tmdev;
> +		tmdev->sensor[i].id = i;
> +		tmdev->sensor[i].tzd =
> +			devm_thermal_zone_of_sensor_register(tmdev->dev,
> +							     i,
> +							     &tmdev->sensor[i],
> +							     &ths_ops);
> +		if (IS_ERR(tmdev->sensor[i].tzd))
> +			return PTR_ERR(tzd);

This should return PTR_ERR(tmdev->sensor[i].tzd). Otherwise this succeeds even
if tz registration fails, and you get NULL pointer exception tryin to udpate
nonexisting tz from the interrupt handler.

regards,
	Ondrej

> +	}
> +
> +	return 0;
> +}
> +
> +static int sun8i_ths_probe(struct platform_device *pdev)
> +{
> +	struct ths_device *tmdev;
> +	struct device *dev = &pdev->dev;
> +	int ret, irq;
> +
> +	tmdev = devm_kzalloc(dev, sizeof(*tmdev), GFP_KERNEL);
> +	if (!tmdev)
> +		return -ENOMEM;
> +
> +	tmdev->dev = dev;
> +	platform_set_drvdata(pdev, tmdev);
> +
> +	ret = sun8i_ths_resource_init(tmdev);
> +	if (ret)
> +		return ret;
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0)
> +		return irq;
> +
> +	ret = sun50i_h6_thermal_init(tmdev);
> +	if (ret)
> +		return ret;
> +
> +	ret = sun8i_ths_register(tmdev);
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * Avoid entering the interrupt handler, the thermal device is not
> +	 * registered yet, we deffer the registration of the interrupt to
> +	 * the end.
> +	 */
> +	ret = devm_request_threaded_irq(dev, irq, NULL,
> +					sun50i_h6_irq_thread,
> +					IRQF_ONESHOT, "ths", tmdev);
> +	if (ret)
> +		return ret;
> +
> +	return ret;
> +}
> +
> +static int sun8i_ths_remove(struct platform_device *pdev)
> +{
> +	struct ths_device *tmdev = platform_get_drvdata(pdev);
> +
> +	clk_disable_unprepare(tmdev->bus_clk);
> +	reset_control_assert(tmdev->reset);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id of_ths_match[] = {
> +	{ .compatible = "allwinner,sun50i-h6-ths"},
> +	{ /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, of_ths_match);
> +
> +static struct platform_driver ths_driver = {
> +	.probe = sun8i_ths_probe,
> +	.remove = sun8i_ths_remove,
> +	.driver = {
> +		.name = "sun8i-thermal",
> +		.of_match_table = of_ths_match,
> +	},
> +};
> +module_platform_driver(ths_driver);
> +
> +MODULE_DESCRIPTION("Thermal sensor driver for Allwinner SOC");
> +MODULE_LICENSE("GPL v2");
> -- 
> 2.17.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 01/18] thermal: sun8i: add thermal driver for h6
  2019-08-10  5:28 ` [PATCH v5 01/18] thermal: sun8i: " Yangtao Li
  2019-09-01  2:06   ` Ondřej Jirman
@ 2019-09-01 21:04   ` Ondřej Jirman
  1 sibling, 0 replies; 43+ messages in thread
From: Ondřej Jirman @ 2019-09-01 21:04 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre, devicetree, linux-kernel,
	linux-arm-kernel, linux-pm

Hello,

On Sat, Aug 10, 2019 at 05:28:12AM +0000, Yangtao Li wrote:
> This patch adds the support for allwinner thermal sensor, within
> allwinner SoC. It will register sensors for thermal framework
> and use device tree to bind cooling device.

I've tested this driver on H6 SoC, and it reports temperatures that are
way too high. It overestimates temperature by around 15-25°C.

I'm measuring the SoC temperature with IR thermometer (it reports temperatures
slightly lower than real ones 2-3°C, when measuring black surfaces).

I've found out that ORing 0x2f to SUN50I_THS_CTRL0 will correct this.

This value is undocummented, but present in BSP:

See: https://megous.com/git/linux/tree/drivers/thermal/sunxi_thermal/sunxi_thermal_sensor/sunxi_ths_driver.h?h=h6-4.9-bsp#n561

With this value set, the driver reports values 7°C above package temperature,
which seems about right.

regards,
	o.

> Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> ---
>  MAINTAINERS                     |   7 +
>  drivers/thermal/Kconfig         |  14 ++
>  drivers/thermal/Makefile        |   1 +
>  drivers/thermal/sun8i_thermal.c | 399 ++++++++++++++++++++++++++++++++
>  4 files changed, 421 insertions(+)
>  create mode 100644 drivers/thermal/sun8i_thermal.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 47800d32cfbc..89dc43f4064d 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -682,6 +682,13 @@ L:	linux-crypto@vger.kernel.org
>  S:	Maintained
>  F:	drivers/crypto/sunxi-ss/
>  
> +ALLWINNER THERMAL DRIVER
> +M:	Yangtao Li <tiny.windzz@gmail.com>
> +L:	linux-pm@vger.kernel.org
> +S:	Maintained
> +F:	Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
> +F:	drivers/thermal/sun8i_thermal.c
> +
>  ALLWINNER VPU DRIVER
>  M:	Maxime Ripard <maxime.ripard@bootlin.com>
>  M:	Paul Kocialkowski <paul.kocialkowski@bootlin.com>
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index 9966364a6deb..f8b73b32b92d 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -262,6 +262,20 @@ config SPEAR_THERMAL
>  	  Enable this to plug the SPEAr thermal sensor driver into the Linux
>  	  thermal framework.
>  
> +config SUN8I_THERMAL
> +	tristate "Allwinner sun8i thermal driver"
> +	depends on ARCH_SUNXI || COMPILE_TEST
> +	depends on HAS_IOMEM
> +	depends on NVMEM
> +	depends on OF
> +	depends on RESET_CONTROLLER
> +	help
> +	  Support for the sun8i thermal sensor driver into the Linux thermal
> +	  framework.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called sun8i-thermal.
> +
>  config ROCKCHIP_THERMAL
>  	tristate "Rockchip thermal driver"
>  	depends on ARCH_ROCKCHIP || COMPILE_TEST
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 74a37c7f847a..fa6f8b206281 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -31,6 +31,7 @@ thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
>  obj-y				+= broadcom/
>  obj-$(CONFIG_THERMAL_MMIO)		+= thermal_mmio.o
>  obj-$(CONFIG_SPEAR_THERMAL)	+= spear_thermal.o
> +obj-$(CONFIG_SUN8I_THERMAL)     += sun8i_thermal.o
>  obj-$(CONFIG_ROCKCHIP_THERMAL)	+= rockchip_thermal.o
>  obj-$(CONFIG_RCAR_THERMAL)	+= rcar_thermal.o
>  obj-$(CONFIG_RCAR_GEN3_THERMAL)	+= rcar_gen3_thermal.o
> diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
> new file mode 100644
> index 000000000000..2ce36fa3fec3
> --- /dev/null
> +++ b/drivers/thermal/sun8i_thermal.c
> @@ -0,0 +1,399 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Thermal sensor driver for Allwinner SOC
> + * Copyright (C) 2019 Yangtao Li
> + *
> + * Based on the work of Icenowy Zheng <icenowy@aosc.io>
> + * Based on the work of Ondrej Jirman <megous@megous.com>
> + * Based on the work of Josef Gajdusek <atx@atx.name>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/interrupt.h>
> +#include <linux/module.h>
> +#include <linux/nvmem-consumer.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +#include <linux/slab.h>
> +#include <linux/thermal.h>
> +
> +#define MAX_SENSOR_NUM	4
> +
> +#define SUN50I_H6_SENSOR_NUM	2
> +#define SUN50I_H6_OFFSET	-2794
> +#define SUN50I_H6_SCALE		-67
> +
> +#define FT_TEMP_MASK				GENMASK(11, 0)
> +#define TEMP_CALIB_MASK				GENMASK(11, 0)
> +#define TEMP_TO_REG				672
> +#define CALIBRATE_DEFAULT			0x800
> +
> +#define SUN50I_THS_CTRL0			0x00
> +#define SUN50I_H6_THS_ENABLE			0x04
> +#define SUN50I_H6_THS_PC			0x08
> +#define SUN50I_H6_THS_DIC			0x10
> +#define SUN50I_H6_THS_DIS			0x20
> +#define SUN50I_H6_THS_MFC			0x30
> +#define SUN50I_H6_THS_TEMP_CALIB		0xa0
> +#define SUN50I_H6_THS_TEMP_DATA			0xc0
> +
> +#define SUN50I_THS_CTRL0_T_ACQ(x)		((GENMASK(15, 0) & (x)) << 16)
> +#define SUN50I_THS_FILTER_EN			BIT(2)
> +#define SUN50I_THS_FILTER_TYPE(x)		(GENMASK(1, 0) & (x))
> +#define SUN50I_H6_THS_PC_TEMP_PERIOD(x)		((GENMASK(19, 0) & (x)) << 12)
> +#define SUN50I_H6_THS_DATA_IRQ_STS(x)		BIT(x)
> +
> +/* millidegree celsius */
> +#define SUN50I_H6_FT_DEVIATION			7000
> +
> +struct ths_device;
> +
> +struct tsensor {
> +	struct ths_device		*tmdev;
> +	struct thermal_zone_device	*tzd;
> +	int				id;
> +};
> +
> +struct ths_device {
> +	struct device				*dev;
> +	struct regmap				*regmap;
> +	struct reset_control			*reset;
> +	struct clk				*bus_clk;
> +	struct tsensor				sensor[MAX_SENSOR_NUM];
> +};
> +
> +/* Temp Unit: millidegree Celsius */
> +static int sun8i_ths_reg2temp(struct ths_device *tmdev,
> +			      int reg)
> +{
> +	return (reg + SUN50I_H6_OFFSET) * SUN50I_H6_SCALE;
> +}
> +
> +static int sun8i_ths_get_temp(void *data, int *temp)
> +{
> +	struct tsensor *s = data;
> +	struct ths_device *tmdev = s->tmdev;
> +	int val;
> +
> +	regmap_read(tmdev->regmap, SUN50I_H6_THS_TEMP_DATA +
> +		    0x4 * s->id, &val);
> +
> +	/* ths have no data yet */
> +	if (!val)
> +		return -EAGAIN;
> +
> +	*temp = sun8i_ths_reg2temp(tmdev, val);
> +	/*
> +	 * XX - According to the original sdk, there are some platforms(rarely)
> +	 * that add a fixed offset value after calculating the temperature
> +	 * value. We can't simply put it on the formula for calculating the
> +	 * temperature above, because the formula for calculating the
> +	 * temperature above is also used when the sensor is calibrated. If
> +	 * do this, the correct calibration formula is hard to know.
> +	 */
> +	*temp += SUN50I_H6_FT_DEVIATION;
> +
> +	return 0;
> +}
> +
> +static const struct thermal_zone_of_device_ops ths_ops = {
> +	.get_temp = sun8i_ths_get_temp,
> +};
> +
> +static const struct regmap_config config = {
> +	.reg_bits = 32,
> +	.val_bits = 32,
> +	.reg_stride = 4,
> +	.fast_io = true,
> +};
> +
> +static irqreturn_t sun50i_h6_irq_thread(int irq, void *data)
> +{
> +	struct ths_device *tmdev = data;
> +	int i, state;
> +
> +	regmap_read(tmdev->regmap, SUN50I_H6_THS_DIS, &state);
> +
> +	for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
> +
> +		if (state & SUN50I_H6_THS_DATA_IRQ_STS(i)) {
> +			/* clear data irq pending */
> +			regmap_write(tmdev->regmap, SUN50I_H6_THS_DIS,
> +				     SUN50I_H6_THS_DATA_IRQ_STS(i));
> +
> +			thermal_zone_device_update(tmdev->sensor[i].tzd,
> +						   THERMAL_EVENT_UNSPECIFIED);
> +		}
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int sun50i_ths_calibrate(struct ths_device *tmdev)
> +{
> +	struct nvmem_cell *calcell;
> +	struct device *dev = tmdev->dev;
> +	u16 *caldata;
> +	size_t callen;
> +	int ft_temp;
> +	int i, ret = 0;
> +
> +	calcell = devm_nvmem_cell_get(dev, "calib");
> +	if (IS_ERR(calcell)) {
> +		if (PTR_ERR(calcell) == -EPROBE_DEFER)
> +			return -EPROBE_DEFER;
> +		/*
> +		 * Even if the external calibration data stored in sid is
> +		 * not accessible, the THS hardware can still work, although
> +		 * the data won't be so accurate.
> +		 *
> +		 * The default value of calibration register is 0x800 for
> +		 * every sensor, and the calibration value is usually 0x7xx
> +		 * or 0x8xx, so they won't be away from the default value
> +		 * for a lot.
> +		 *
> +		 * So here we do not return error if the calibartion data is
> +		 * not available, except the probe needs deferring.
> +		 */
> +		goto out;
> +	}
> +
> +	caldata = nvmem_cell_read(calcell, &callen);
> +	if (IS_ERR(caldata)) {
> +		ret = PTR_ERR(caldata);
> +		goto out;
> +	}
> +
> +	if (!caldata[0] || callen < 2 + 2 * SUN50I_H6_SENSOR_NUM) {
> +		ret = -EINVAL;
> +		goto out_free;
> +	}
> +
> +	/*
> +	 * efuse layout:
> +	 *
> +	 *	0   11  16	 32
> +	 *	+-------+-------+-------+
> +	 *	|temp|  |sensor0|sensor1|
> +	 *	+-------+-------+-------+
> +	 *
> +	 * The calibration data on the H6 is the ambient temperature and
> +	 * sensor values that are filled during the factory test stage.
> +	 *
> +	 * The unit of stored FT temperature is 0.1 degreee celusis.
> +	 * Through the stored ambient temperature and the data read
> +	 * by the sensor, after a certain calculation, the calibration
> +	 * value to be compensated can be obtained.
> +	 */
> +	ft_temp = caldata[0] & FT_TEMP_MASK;
> +
> +	for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
> +		int reg = (int)caldata[i + 1];
> +		int sensor_temp = sun8i_ths_reg2temp(tmdev, reg);
> +		int delta, cdata, offset;
> +
> +		/*
> +		 * To calculate the calibration value:
> +		 *
> +		 * X(in Celsius) = Ts - ft_temp
> +		 * delta = X * 10000 / TEMP_TO_REG
> +		 * cdata = CALIBRATE_DEFAULT - delta
> +		 *
> +		 * cdata: calibration value
> +		 */
> +		delta = (sensor_temp - ft_temp * 100) * 10 / TEMP_TO_REG;
> +		cdata = CALIBRATE_DEFAULT - delta;
> +		if (cdata & ~TEMP_CALIB_MASK) {
> +			/*
> +			 * Calibration value more than 12-bit, but calibration
> +			 * register is 12-bit. In this case, ths hardware can
> +			 * still work without calibration, although the data
> +			 * won't be so accurate.
> +			 */
> +			dev_warn(dev, "sensor%d is not calibrated.\n", i);
> +
> +			continue;
> +		}
> +
> +		offset = (i % 2) << 4;
> +		regmap_update_bits(tmdev->regmap,
> +				   SUN50I_H6_THS_TEMP_CALIB + ((i >> 1) * 4),
> +				   0xfff << offset,
> +				   cdata << offset);
> +	}
> +
> +out_free:
> +	kfree(caldata);
> +out:
> +	return ret;
> +}
> +
> +static int sun8i_ths_resource_init(struct ths_device *tmdev)
> +{
> +	struct device *dev = tmdev->dev;
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct resource *mem;
> +	void __iomem *base;
> +	int ret;
> +
> +	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	base = devm_ioremap_resource(dev, mem);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	tmdev->regmap = devm_regmap_init_mmio(dev, base, &config);
> +	if (IS_ERR(tmdev->regmap))
> +		return PTR_ERR(tmdev->regmap);
> +
> +	tmdev->reset = devm_reset_control_get(dev, 0);
> +	if (IS_ERR(tmdev->reset))
> +		return PTR_ERR(tmdev->reset);
> +
> +	tmdev->bus_clk = devm_clk_get(&pdev->dev, "bus");
> +	if (IS_ERR(tmdev->bus_clk))
> +		return PTR_ERR(tmdev->bus_clk);
> +
> +	ret = reset_control_deassert(tmdev->reset);
> +	if (ret)
> +		return ret;
> +
> +	ret = clk_prepare_enable(tmdev->bus_clk);
> +	if (ret)
> +		goto assert_reset;
> +
> +	ret = sun50i_ths_calibrate(tmdev);
> +	if (ret)
> +		goto bus_disable;
> +
> +	return 0;
> +
> +bus_disable:
> +	clk_disable_unprepare(tmdev->bus_clk);
> +assert_reset:
> +	reset_control_assert(tmdev->reset);
> +
> +	return ret;
> +}
> +
> +static int sun50i_h6_thermal_init(struct ths_device *tmdev)
> +{
> +	int val;
> +
> +	/*
> +	 * clkin = 24MHz
> +	 * T acquire = clkin / (x + 1)
> +	 *           = 20us
> +	 */
> +	regmap_write(tmdev->regmap, SUN50I_THS_CTRL0,
> +		     SUN50I_THS_CTRL0_T_ACQ(479));
> +	/* average over 4 samples */
> +	regmap_write(tmdev->regmap, SUN50I_H6_THS_MFC,
> +		     SUN50I_THS_FILTER_EN |
> +		     SUN50I_THS_FILTER_TYPE(1));
> +	/* period = (x + 1) * 4096 / clkin; ~10ms */
> +	regmap_write(tmdev->regmap, SUN50I_H6_THS_PC,
> +		     SUN50I_H6_THS_PC_TEMP_PERIOD(58));
> +	/* enable sensor */
> +	val = GENMASK(SUN50I_H6_SENSOR_NUM - 1, 0);
> +	regmap_write(tmdev->regmap, SUN50I_H6_THS_ENABLE, val);
> +	/* thermal data interrupt enable */
> +	val = GENMASK(SUN50I_H6_SENSOR_NUM - 1, 0);
> +	regmap_write(tmdev->regmap, SUN50I_H6_THS_DIC, val);
> +
> +	return 0;
> +}
> +
> +static int sun8i_ths_register(struct ths_device *tmdev)
> +{
> +	struct thermal_zone_device *tzd;
> +	int i;
> +
> +	for (i = 0; i < SUN50I_H6_SENSOR_NUM; i++) {
> +		tmdev->sensor[i].tmdev = tmdev;
> +		tmdev->sensor[i].id = i;
> +		tmdev->sensor[i].tzd =
> +			devm_thermal_zone_of_sensor_register(tmdev->dev,
> +							     i,
> +							     &tmdev->sensor[i],
> +							     &ths_ops);
> +		if (IS_ERR(tmdev->sensor[i].tzd))
> +			return PTR_ERR(tzd);
> +	}
> +
> +	return 0;
> +}
> +
> +static int sun8i_ths_probe(struct platform_device *pdev)
> +{
> +	struct ths_device *tmdev;
> +	struct device *dev = &pdev->dev;
> +	int ret, irq;
> +
> +	tmdev = devm_kzalloc(dev, sizeof(*tmdev), GFP_KERNEL);
> +	if (!tmdev)
> +		return -ENOMEM;
> +
> +	tmdev->dev = dev;
> +	platform_set_drvdata(pdev, tmdev);
> +
> +	ret = sun8i_ths_resource_init(tmdev);
> +	if (ret)
> +		return ret;
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0)
> +		return irq;
> +
> +	ret = sun50i_h6_thermal_init(tmdev);
> +	if (ret)
> +		return ret;
> +
> +	ret = sun8i_ths_register(tmdev);
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * Avoid entering the interrupt handler, the thermal device is not
> +	 * registered yet, we deffer the registration of the interrupt to
> +	 * the end.
> +	 */
> +	ret = devm_request_threaded_irq(dev, irq, NULL,
> +					sun50i_h6_irq_thread,
> +					IRQF_ONESHOT, "ths", tmdev);
> +	if (ret)
> +		return ret;
> +
> +	return ret;
> +}
> +
> +static int sun8i_ths_remove(struct platform_device *pdev)
> +{
> +	struct ths_device *tmdev = platform_get_drvdata(pdev);
> +
> +	clk_disable_unprepare(tmdev->bus_clk);
> +	reset_control_assert(tmdev->reset);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id of_ths_match[] = {
> +	{ .compatible = "allwinner,sun50i-h6-ths"},
> +	{ /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, of_ths_match);
> +
> +static struct platform_driver ths_driver = {
> +	.probe = sun8i_ths_probe,
> +	.remove = sun8i_ths_remove,
> +	.driver = {
> +		.name = "sun8i-thermal",
> +		.of_match_table = of_ths_match,
> +	},
> +};
> +module_platform_driver(ths_driver);
> +
> +MODULE_DESCRIPTION("Thermal sensor driver for Allwinner SOC");
> +MODULE_LICENSE("GPL v2");
> -- 
> 2.17.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 00/18] add thermal driver for h6
  2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
                   ` (18 preceding siblings ...)
  2019-08-11 21:14 ` [PATCH v5 00/18] add thermal driver for h6 Clément Péron
@ 2019-09-01 21:52 ` Ondřej Jirman
  2019-09-02  7:27   ` Maxime Ripard
  19 siblings, 1 reply; 43+ messages in thread
From: Ondřej Jirman @ 2019-09-01 21:52 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre, devicetree, linux-kernel,
	linux-arm-kernel, linux-pm

Hello Yangtao,

On Sat, Aug 10, 2019 at 05:28:11AM +0000, Yangtao Li wrote:
> This patchset add support for A64, H3, H5, H6 and R40 thermal sensor.
> 
> Thx to Icenowy and Vasily.
> 
> BTY, do a cleanup in thermal makfile.

I've added support for A83T and also some cleanups, according to my
feedback:

https://megous.com/git/linux/log/?h=ths-5.3

Feel free to pick up whatever you like from that tree.

For others, there are also DTS patches in that tree for H3, H5, A83T, and H6, so
that shoul make testing of this driver easier.

regards,
	Ondrej

> Icenowy Zheng (3):
>   thermal: sun8i: allow to use custom temperature calculation function
>   thermal: sun8i: add support for Allwinner H5 thermal sensor
>   thermal: sun8i: add support for Allwinner R40 thermal sensor
> 
> Vasily Khoruzhick (1):
>   thermal: sun8i: add thermal driver for A64
> 
> Yangtao Li (14):
>   thermal: sun8i: add thermal driver for h6
>   dt-bindings: thermal: add binding document for h6 thermal controller
>   thermal: fix indentation in makefile
>   thermal: sun8i: get ths sensor number from device compatible
>   thermal: sun8i: rework for sun8i_ths_get_temp()
>   thermal: sun8i: get ths init func from device compatible
>   thermal: sun8i: rework for ths irq handler func
>   thermal: sun8i: support mod clocks
>   thermal: sun8i: rework for ths calibrate func
>   dt-bindings: thermal: add binding document for h3 thermal controller
>   thermal: sun8i: add thermal driver for h3
>   dt-bindings: thermal: add binding document for a64 thermal controller
>   dt-bindings: thermal: add binding document for h5 thermal controller
>   dt-bindings: thermal: add binding document for r40 thermal controller
> 
>  .../bindings/thermal/sun8i-thermal.yaml       | 157 +++++
>  MAINTAINERS                                   |   7 +
>  drivers/thermal/Kconfig                       |  14 +
>  drivers/thermal/Makefile                      |   9 +-
>  drivers/thermal/sun8i_thermal.c               | 596 ++++++++++++++++++
>  5 files changed, 779 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
>  create mode 100644 drivers/thermal/sun8i_thermal.c
> 
> ---
> v5:
> -add more support
> -some trival fix
> ---
> 2.17.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 00/18] add thermal driver for h6
  2019-09-01 21:52 ` Ondřej Jirman
@ 2019-09-02  7:27   ` Maxime Ripard
  2019-09-02 10:58     ` Ondřej Jirman
  0 siblings, 1 reply; 43+ messages in thread
From: Maxime Ripard @ 2019-09-02  7:27 UTC (permalink / raw)
  To: Yangtao Li, rui.zhang, edubezval, daniel.lezcano, robh+dt,
	mark.rutland, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre, devicetree, linux-kernel,
	linux-arm-kernel, linux-pm

Hi,

On Sun, Sep 01, 2019 at 11:52:14PM +0200, Ondřej Jirman wrote:
> Hello Yangtao,
>
> On Sat, Aug 10, 2019 at 05:28:11AM +0000, Yangtao Li wrote:
> > This patchset add support for A64, H3, H5, H6 and R40 thermal sensor.
> >
> > Thx to Icenowy and Vasily.
> >
> > BTY, do a cleanup in thermal makfile.
>
> I've added support for A83T and also some cleanups, according to my
> feedback:
>
> https://megous.com/git/linux/log/?h=ths-5.3
>
> Feel free to pick up whatever you like from that tree.
>
> For others, there are also DTS patches in that tree for H3, H5, A83T, and H6, so
> that shoul make testing of this driver easier.

I'm not convinced that always expanding the number of SoC supported is
the best strategy to get this merged. Usually, keeping the same
feature set across version, consolidating that, and then once it's in
sending the new SoC support works best.

Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 00/18] add thermal driver for h6
  2019-09-02  7:27   ` Maxime Ripard
@ 2019-09-02 10:58     ` Ondřej Jirman
  0 siblings, 0 replies; 43+ messages in thread
From: Ondřej Jirman @ 2019-09-02 10:58 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Yangtao Li, rui.zhang, edubezval, daniel.lezcano, robh+dt,
	mark.rutland, wens, mchehab+samsung, davem, gregkh,
	Jonathan.Cameron, nicolas.ferre, devicetree, linux-kernel,
	linux-arm-kernel, linux-pm

Hello Maxime,

On Mon, Sep 02, 2019 at 09:27:35AM +0200, Maxime Ripard wrote:
> Hi,
> 
> On Sun, Sep 01, 2019 at 11:52:14PM +0200, Ondřej Jirman wrote:
> > Hello Yangtao,
> >
> > On Sat, Aug 10, 2019 at 05:28:11AM +0000, Yangtao Li wrote:
> > > This patchset add support for A64, H3, H5, H6 and R40 thermal sensor.
> > >
> > > Thx to Icenowy and Vasily.
> > >
> > > BTY, do a cleanup in thermal makfile.
> >
> > I've added support for A83T and also some cleanups, according to my
> > feedback:
> >
> > https://megous.com/git/linux/log/?h=ths-5.3
> >
> > Feel free to pick up whatever you like from that tree.
> >
> > For others, there are also DTS patches in that tree for H3, H5, A83T, and H6, so
> > that shoul make testing of this driver easier.
> 
> I'm not convinced that always expanding the number of SoC supported is
> the best strategy to get this merged. Usually, keeping the same
> feature set across version, consolidating that, and then once it's in
> sending the new SoC support works best.

That's fine and all, but I've mostly added DT descriptions for already supported
SoCs and fixed bugs in the driver, so that people can actually test the existing
driver.

I think adding DT changes will actually help get needed exposure for this
patch series.

A83T support that I added, was actually just a small change to the driver.

regards,
	o.

> Maxime
> 
> --
> Maxime Ripard, Bootlin
> Embedded Linux and Kernel engineering
> https://bootlin.com
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH v5 08/18] thermal: sun8i: support mod clocks
  2019-08-25 16:14             ` Frank Lee
@ 2019-10-21  3:41               ` Vasily Khoruzhick
  0 siblings, 0 replies; 43+ messages in thread
From: Vasily Khoruzhick @ 2019-10-21  3:41 UTC (permalink / raw)
  To: Frank Lee
  Cc: Mark Rutland, devicetree, Linux PM, Maxime Ripard,
	Greg Kroah-Hartman, Daniel Lezcano, linux-kernel,
	Eduardo Valentin, Chen-Yu Tsai, Rob Herring, Jonathan.Cameron,
	Mauro Carvalho Chehab, rui.zhang, David S. Miller, arm-linux

On Sun, Aug 25, 2019 at 9:14 AM Frank Lee <tiny.windzz@gmail.com> wrote:
>
> HI Vasily,

Hi Yangtao,

Sorry for the late reply,

> On Wed, Aug 14, 2019 at 11:01 AM Vasily Khoruzhick <anarsoul@gmail.com> wrote:
> >
> > On Tue, Aug 13, 2019 at 1:06 PM Ondřej Jirman <megous@megous.com> wrote:
> > >
> > > On Mon, Aug 12, 2019 at 04:54:15PM -0700, Vasily Khoruzhick wrote:
> > > > On Mon, Aug 12, 2019 at 4:46 PM Frank Lee <tiny.windzz@gmail.com> wrote:
> > > > >
> > > > > HI Vasily,
> > > > >
> > > > > On Sat, Aug 10, 2019 at 2:17 PM Vasily Khoruzhick <anarsoul@gmail.com> wrote:
> > > > > >
> > > > > > On Fri, Aug 9, 2019 at 10:31 PM Yangtao Li <tiny.windzz@gmail.com> wrote:
> > > > > > >
> > > > > > > H3 has extra clock, so introduce something in ths_thermal_chip/ths_device
> > > > > > > and adds the process of the clock.
> > > > > > >
> > > > > > > This is pre-work for supprt it.
> > > > > > >
> > > > > > > Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> > > > > > > ---
> > > > > > >  drivers/thermal/sun8i_thermal.c | 17 ++++++++++++++++-
> > > > > > >  1 file changed, 16 insertions(+), 1 deletion(-)
> > > > > > >
> > > > > > > diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
> > > > > > > index b934bc81eba7..6f4294c2aba7 100644
> > > > > > > --- a/drivers/thermal/sun8i_thermal.c
> > > > > > > +++ b/drivers/thermal/sun8i_thermal.c
> > > > > > > @@ -54,6 +54,7 @@ struct tsensor {
> > > > > > >  };
> > > > > > >
> > > > > > >  struct ths_thermal_chip {
> > > > > > > +       bool            has_mod_clk;
> > > > > > >         int             sensor_num;
> > > > > > >         int             offset;
> > > > > > >         int             scale;
> > > > > > > @@ -69,6 +70,7 @@ struct ths_device {
> > > > > > >         struct regmap                           *regmap;
> > > > > > >         struct reset_control                    *reset;
> > > > > > >         struct clk                              *bus_clk;
> > > > > > > +       struct clk                              *mod_clk;
> > > > > > >         struct tsensor                          sensor[MAX_SENSOR_NUM];
> > > > > > >  };
> > > > > > >
> > > > > > > @@ -274,6 +276,12 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
> > > > > > >         if (IS_ERR(tmdev->bus_clk))
> > > > > > >                 return PTR_ERR(tmdev->bus_clk);
> > > > > > >
> > > > > > > +       if (tmdev->chip->has_mod_clk) {
> > > > > > > +               tmdev->mod_clk = devm_clk_get(&pdev->dev, "mod");
> > > > > > > +               if (IS_ERR(tmdev->mod_clk))
> > > > > > > +                       return PTR_ERR(tmdev->mod_clk);
> > > > > > > +       }
> > > > > > > +
> > > > > > >         ret = reset_control_deassert(tmdev->reset);
> > > > > > >         if (ret)
> > > > > > >                 return ret;
> > > > > > > @@ -282,12 +290,18 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
> > > > > > >         if (ret)
> > > > > > >                 goto assert_reset;
> > > > > > >
> > > > > > > -       ret = sun50i_ths_calibrate(tmdev);
> > > > > > > +       ret = clk_prepare_enable(tmdev->mod_clk);
> > > > > >
> > > > > > You have to set rate of modclk before enabling it since you can't rely
> > > > > > on whatever bootloader left for you.
> > > > > >
> > > > > > Also I found that parameters you're using for PC_TEMP_PERIOD, ACQ0 and
> > > > > > ACQ1 are too aggressive and may result in high interrupt rate to the
> > > > > > point when it may stall RCU. I changed driver a bit to use params from
> > > > > > Philipp Rossak's work (modclk set to 4MHz, PC_TEMP_PERIOD is 7, ACQ0
> > > > > > is 255, ACQ1 is 63) and it fixed RCU stalls for me, see [1] for
> > > > > > details.
> > > > >
> > > > > Why is the RCU stall happening, is it caused by a deadlock?
> > > > > Can you provide log information and your configuration?
> > > > > I am a bit curious.
> > > >
> > > > It's not deadlock, I believe it just can't handle that many interrupts
> > > > when running at lowest CPU frequency. Even with Philipp's settings
> > > > there's ~20 interrupts a second from ths. I don't remember how many
> > > > interrupts were there with your settings.
> > > >
> > > > Unfortunately there's nothing interesting in backtraces, I'm using
> > > > Pine64-LTS board.
> > >
> > > Recently there was a similar issue, with buggy CCU driver that caused
> > > CIR interrupts being fired constantly, and it also resulted in RCU
> > > stalls. Looks like a comon cause of RCU stalls.
> > >
> > > THS timing settings probably need to be made specific to the SoC, because
> > > I noticed that the same settings lead to wildly different timings on
> > > different SoCs.
> > >
> > > It would be good to measure how often ths interrupt fires with this driver
> > > on various SoCs.
> > >
> > > 20 times a second and more sounds like overkill. I'd expect a useful
> > > range to be at most 5-10 times a second. That should be enough to stop
> > > overheating the SoC due to suddenly increased load, even without a
> > > heatsink.
> >
> > Note that A64 has 3 sensors and each sensor has individual interrupt,
> > so technically it's 6-7 interrupts per sensor per second
>
> You only need to increase the value of the period to reduce the number
> of interrupts.
> Can you test the relationship between the period and the number of interrupts
> when the mod clock does not change and stays 24M?

I played a bit with your settings and 24M,

with PERIOD = 57 I get 26 interrupts / second
with 87 - 18 interrupts / second
with 116 - 12-15 interrupts / second.

I think we should use 116 for A64 since with it we get reasonable
number of ths interrupts in a second.

Regards,
Vasily

> Thx.
> Yangtao
>
> >
> > > regards,
> > >         o.
> > >
> > > > > Thx,
> > > > > Yangtao
> > > > >
> > > > > >
> > > > > > [1] https://github.com/anarsoul/linux-2.6/commit/46b8bb0fe2ccd1cd88fa9181a2ecbf79e8d513b2
> > > > > >
> > > > > >
> > > > > > >         if (ret)
> > > > > > >                 goto bus_disable;
> > > > > > >
> > > > > > > +       ret = sun50i_ths_calibrate(tmdev);
> > > > > > > +       if (ret)
> > > > > > > +               goto mod_disable;
> > > > > > > +
> > > > > > >         return 0;
> > > > > > >
> > > > > > > +mod_disable:
> > > > > > > +       clk_disable_unprepare(tmdev->mod_clk);
> > > > > > >  bus_disable:
> > > > > > >         clk_disable_unprepare(tmdev->bus_clk);
> > > > > > >  assert_reset:
> > > > > > > @@ -395,6 +409,7 @@ static int sun8i_ths_remove(struct platform_device *pdev)
> > > > > > >  {
> > > > > > >         struct ths_device *tmdev = platform_get_drvdata(pdev);
> > > > > > >
> > > > > > > +       clk_disable_unprepare(tmdev->mod_clk);
> > > > > > >         clk_disable_unprepare(tmdev->bus_clk);
> > > > > > >         reset_control_assert(tmdev->reset);
> > > > > > >
> > > > > > > --
> > > > > > > 2.17.1
> > > > > > >
> > > > > > >
> > > > > > > _______________________________________________
> > > > > > > linux-arm-kernel mailing list
> > > > > > > linux-arm-kernel@lists.infradead.org
> > > > > > > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> > > >
> > > > _______________________________________________
> > > > linux-arm-kernel mailing list
> > > > linux-arm-kernel@lists.infradead.org
> > > > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 43+ messages in thread

end of thread, back to index

Thread overview: 43+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-10  5:28 [PATCH v5 00/18] add thermal driver for h6 Yangtao Li
2019-08-10  5:28 ` [PATCH v5 01/18] thermal: sun8i: " Yangtao Li
2019-09-01  2:06   ` Ondřej Jirman
2019-09-01 21:04   ` Ondřej Jirman
2019-08-10  5:28 ` [PATCH v5 02/18] dt-bindings: thermal: add binding document for h6 thermal controller Yangtao Li
2019-08-12  8:56   ` Maxime Ripard
2019-08-12 23:40     ` Frank Lee
2019-08-16  9:47       ` Maxime Ripard
2019-08-10  5:28 ` [PATCH v5 03/18] thermal: fix indentation in makefile Yangtao Li
2019-08-28 12:40   ` Zhang Rui
2019-08-10  5:28 ` [PATCH v5 04/18] thermal: sun8i: get ths sensor number from device compatible Yangtao Li
2019-08-10  5:28 ` [PATCH v5 05/18] thermal: sun8i: rework for sun8i_ths_get_temp() Yangtao Li
2019-08-10  5:28 ` [PATCH v5 06/18] thermal: sun8i: get ths init func from device compatible Yangtao Li
2019-08-10  5:28 ` [PATCH v5 07/18] thermal: sun8i: rework for ths irq handler func Yangtao Li
2019-08-10  5:28 ` [PATCH v5 08/18] thermal: sun8i: support mod clocks Yangtao Li
2019-08-10  6:16   ` Vasily Khoruzhick
2019-08-12 23:46     ` Frank Lee
2019-08-12 23:54       ` Vasily Khoruzhick
2019-08-13 20:06         ` Ondřej Jirman
2019-08-14  3:01           ` Vasily Khoruzhick
2019-08-25 16:14             ` Frank Lee
2019-10-21  3:41               ` Vasily Khoruzhick
2019-08-10  5:28 ` [PATCH v5 09/18] thermal: sun8i: rework for ths calibrate func Yangtao Li
2019-08-28 12:45   ` Zhang Rui
2019-08-10  5:28 ` [PATCH v5 10/18] dt-bindings: thermal: add binding document for h3 thermal controller Yangtao Li
2019-08-27 15:26   ` Rob Herring
2019-08-10  5:28 ` [PATCH v5 11/18] thermal: sun8i: add thermal driver for h3 Yangtao Li
2019-08-10  5:28 ` [PATCH v5 12/18] dt-bindings: thermal: add binding document for a64 thermal controller Yangtao Li
2019-08-27 15:26   ` Rob Herring
2019-08-10  5:28 ` [PATCH v5 13/18] thermal: sun8i: add thermal driver for A64 Yangtao Li
2019-08-10  5:28 ` [PATCH v5 14/18] dt-bindings: thermal: add binding document for h5 thermal controller Yangtao Li
2019-08-27 15:27   ` Rob Herring
2019-08-10  5:28 ` [PATCH v5 15/18] thermal: sun8i: allow to use custom temperature calculation function Yangtao Li
2019-08-12  8:49   ` Maxime Ripard
2019-08-10  5:28 ` [PATCH v5 16/18] thermal: sun8i: add support for Allwinner H5 thermal sensor Yangtao Li
2019-08-10  5:28 ` [PATCH v5 17/18] dt-bindings: thermal: add binding document for r40 thermal controller Yangtao Li
2019-08-27 15:27   ` Rob Herring
2019-08-10  5:28 ` [PATCH v5 18/18] thermal: sun8i: add support for Allwinner R40 thermal sensor Yangtao Li
2019-08-11 21:14 ` [PATCH v5 00/18] add thermal driver for h6 Clément Péron
2019-08-12 23:36   ` Frank Lee
2019-09-01 21:52 ` Ondřej Jirman
2019-09-02  7:27   ` Maxime Ripard
2019-09-02 10:58     ` Ondřej Jirman

Linux-PM Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-pm/0 linux-pm/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-pm linux-pm/ https://lore.kernel.org/linux-pm \
		linux-pm@vger.kernel.org linux-pm@archiver.kernel.org
	public-inbox-index linux-pm

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-pm


AGPL code for this site: git clone https://public-inbox.org/ public-inbox