Linux-PM Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v4 00/11] add thermal driver for h6
@ 2019-06-23 16:41 Yangtao Li
  2019-06-23 16:41 ` [PATCH v4 01/11] thermal: sun8i: " Yangtao Li
                   ` (11 more replies)
  0 siblings, 12 replies; 21+ messages in thread
From: Yangtao Li @ 2019-06-23 16:41 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, davem, gregkh, mchehab+samsung,
	linus.walleij, nicolas.ferre, paulmck
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-kernel, Yangtao Li

This patchset add support for H3 and H6 thermal sensor.

BTY, do a cleanup in thermal makfile.

Yangtao Li (11):
  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 ahb 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

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

---
v4:
-add h3 support
-fix yaml file
---
2.17.1


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

* [PATCH v4 01/11] thermal: sun8i: add thermal driver for h6
  2019-06-23 16:41 [PATCH v4 00/11] add thermal driver for h6 Yangtao Li
@ 2019-06-23 16:41 ` " Yangtao Li
  2019-06-24 12:07   ` Ondřej Jirman
  2019-06-23 16:41 ` [PATCH v4 02/11] dt-bindings: thermal: add binding document for h6 thermal controller Yangtao Li
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 21+ messages in thread
From: Yangtao Li @ 2019-06-23 16:41 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, davem, gregkh, mchehab+samsung,
	linus.walleij, nicolas.ferre, paulmck
  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 | 405 ++++++++++++++++++++++++++++++++
 4 files changed, 427 insertions(+)
 create mode 100644 drivers/thermal/sun8i_thermal.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 36a84614d6c3..67e7fcfaded2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -674,6 +674,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..d6918c62682b
--- /dev/null
+++ b/drivers/thermal/sun8i_thermal.c
@@ -0,0 +1,405 @@
+// 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 -EBUSY;
+
+	*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, calib_offest;
+
+		/*
+		 * 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;
+		}
+
+		calib_offest = SUN50I_H6_THS_TEMP_CALIB + (i / 2) * 0x4;
+
+		if (i % 2) {
+			int val;
+
+			regmap_read(tmdev->regmap, calib_offest, &val);
+			val = (val & TEMP_CALIB_MASK) | (cdata << 16);
+			regmap_write(tmdev->regmap, calib_offest, val);
+		} else {
+			regmap_write(tmdev->regmap, calib_offest, cdata);
+		}
+	}
+
+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_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_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] 21+ messages in thread

* [PATCH v4 02/11] dt-bindings: thermal: add binding document for h6 thermal controller
  2019-06-23 16:41 [PATCH v4 00/11] add thermal driver for h6 Yangtao Li
  2019-06-23 16:41 ` [PATCH v4 01/11] thermal: sun8i: " Yangtao Li
@ 2019-06-23 16:41 ` Yangtao Li
  2019-06-24  8:47   ` Maxime Ripard
  2019-06-23 16:41 ` [PATCH v4 03/11] thermal: fix indentation in makefile Yangtao Li
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 21+ messages in thread
From: Yangtao Li @ 2019-06-23 16:41 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, davem, gregkh, mchehab+samsung,
	linus.walleij, nicolas.ferre, paulmck
  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       | 71 +++++++++++++++++++
 1 file changed, 71 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..2c5acc61ed03
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
@@ -0,0 +1,71 @@
+# 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:
+    minItems: 1
+    maxItems: 1
+
+  clock-names:
+    const: bus
+
+  '#thermal-sensor-cells':
+    const: 1
+
+  nvmem-cells:
+    items:
+      - description: ths calibrate data
+
+  nvmem-cell-names:
+    items:
+      - const: calib
+
+required:
+  - compatible
+  - reg
+  - reset
+  - clocks
+  - clock-names
+  - interrupts
+  - '#thermal-sensor-cells'
+
+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>;
+    };
+
+...
-- 
2.17.1


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

* [PATCH v4 03/11] thermal: fix indentation in makefile
  2019-06-23 16:41 [PATCH v4 00/11] add thermal driver for h6 Yangtao Li
  2019-06-23 16:41 ` [PATCH v4 01/11] thermal: sun8i: " Yangtao Li
  2019-06-23 16:41 ` [PATCH v4 02/11] dt-bindings: thermal: add binding document for h6 thermal controller Yangtao Li
@ 2019-06-23 16:41 ` Yangtao Li
  2019-06-23 16:41 ` [PATCH v4 04/11] thermal: sun8i: get ths sensor number from device compatible Yangtao Li
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 21+ messages in thread
From: Yangtao Li @ 2019-06-23 16:41 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, davem, gregkh, mchehab+samsung,
	linus.walleij, nicolas.ferre, paulmck
  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] 21+ messages in thread

* [PATCH v4 04/11] thermal: sun8i: get ths sensor number from device compatible
  2019-06-23 16:41 [PATCH v4 00/11] add thermal driver for h6 Yangtao Li
                   ` (2 preceding siblings ...)
  2019-06-23 16:41 ` [PATCH v4 03/11] thermal: fix indentation in makefile Yangtao Li
@ 2019-06-23 16:41 ` Yangtao Li
  2019-06-23 16:42 ` [PATCH v4 05/11] thermal: sun8i: rework for sun8i_ths_get_temp() Yangtao Li
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 21+ messages in thread
From: Yangtao Li @ 2019-06-23 16:41 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, davem, gregkh, mchehab+samsung,
	linus.walleij, nicolas.ferre, paulmck
  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 d6918c62682b..c37e1c51a543 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, calib_offest;
@@ -303,10 +307,10 @@ static int sun50i_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;
@@ -317,7 +321,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 =
@@ -343,6 +347,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);
@@ -385,8 +393,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] 21+ messages in thread

* [PATCH v4 05/11] thermal: sun8i: rework for sun8i_ths_get_temp()
  2019-06-23 16:41 [PATCH v4 00/11] add thermal driver for h6 Yangtao Li
                   ` (3 preceding siblings ...)
  2019-06-23 16:41 ` [PATCH v4 04/11] thermal: sun8i: get ths sensor number from device compatible Yangtao Li
@ 2019-06-23 16:42 ` Yangtao Li
  2019-06-23 16:42 ` [PATCH v4 06/11] thermal: sun8i: get ths init func from device compatible Yangtao Li
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 21+ messages in thread
From: Yangtao Li @ 2019-06-23 16:42 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, davem, gregkh, mchehab+samsung,
	linus.walleij, nicolas.ferre, paulmck
  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 c37e1c51a543..e473a5651436 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;
 }
@@ -395,6 +396,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] 21+ messages in thread

* [PATCH v4 06/11] thermal: sun8i: get ths init func from device compatible
  2019-06-23 16:41 [PATCH v4 00/11] add thermal driver for h6 Yangtao Li
                   ` (4 preceding siblings ...)
  2019-06-23 16:42 ` [PATCH v4 05/11] thermal: sun8i: rework for sun8i_ths_get_temp() Yangtao Li
@ 2019-06-23 16:42 ` Yangtao Li
  2019-06-23 16:42 ` [PATCH v4 07/11] thermal: sun8i: rework for ths irq handler func Yangtao Li
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 21+ messages in thread
From: Yangtao Li @ 2019-06-23 16:42 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, davem, gregkh, mchehab+samsung,
	linus.walleij, nicolas.ferre, paulmck
  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 e473a5651436..59acbbac76e4 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 {
@@ -362,7 +363,7 @@ static int sun8i_ths_probe(struct platform_device *pdev)
 	if (irq < 0)
 		return irq;
 
-	ret = sun50i_thermal_init(tmdev);
+	ret = tmdev->chip->init(tmdev);
 	if (ret)
 		return ret;
 
@@ -400,6 +401,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_thermal_init,
 };
 
 static const struct of_device_id of_ths_match[] = {
-- 
2.17.1


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

* [PATCH v4 07/11] thermal: sun8i: rework for ths irq handler func
  2019-06-23 16:41 [PATCH v4 00/11] add thermal driver for h6 Yangtao Li
                   ` (5 preceding siblings ...)
  2019-06-23 16:42 ` [PATCH v4 06/11] thermal: sun8i: get ths init func from device compatible Yangtao Li
@ 2019-06-23 16:42 ` Yangtao Li
  2019-06-23 16:42 ` [PATCH v4 08/11] thermal: sun8i: support ahb clocks Yangtao Li
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 21+ messages in thread
From: Yangtao Li @ 2019-06-23 16:42 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, davem, gregkh, mchehab+samsung,
	linus.walleij, nicolas.ferre, paulmck
  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 59acbbac76e4..ed1c19bb27cf 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;
@@ -377,7 +389,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;
@@ -402,6 +414,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_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] 21+ messages in thread

* [PATCH v4 08/11] thermal: sun8i: support ahb clocks
  2019-06-23 16:41 [PATCH v4 00/11] add thermal driver for h6 Yangtao Li
                   ` (6 preceding siblings ...)
  2019-06-23 16:42 ` [PATCH v4 07/11] thermal: sun8i: rework for ths irq handler func Yangtao Li
@ 2019-06-23 16:42 ` Yangtao Li
  2019-06-24 18:23   ` Maxime Ripard
  2019-06-23 16:42 ` [PATCH v4 09/11] thermal: sun8i: rework for ths calibrate func Yangtao Li
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 21+ messages in thread
From: Yangtao Li @ 2019-06-23 16:42 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, davem, gregkh, mchehab+samsung,
	linus.walleij, nicolas.ferre, paulmck
  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 ed1c19bb27cf..04f53ffb6a14 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_ahb_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                              *ahb_clk;
 	struct tsensor				sensor[MAX_SENSOR_NUM];
 };
 
@@ -280,6 +282,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_ahb_clk) {
+		tmdev->ahb_clk = devm_clk_get(&pdev->dev, "ahb");
+		if (IS_ERR(tmdev->ahb_clk))
+			return PTR_ERR(tmdev->ahb_clk);
+	}
+
 	ret = reset_control_deassert(tmdev->reset);
 	if (ret)
 		return ret;
@@ -288,12 +296,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->ahb_clk);
 	if (ret)
 		goto bus_disable;
 
+	ret = sun50i_ths_calibrate(tmdev);
+	if (ret)
+		goto ahb_disable;
+
 	return 0;
 
+ahb_disable:
+	clk_disable_unprepare(tmdev->ahb_clk);
 bus_disable:
 	clk_disable_unprepare(tmdev->bus_clk);
 assert_reset:
@@ -401,6 +415,7 @@ static int sun8i_ths_remove(struct platform_device *pdev)
 {
 	struct ths_device *tmdev = platform_get_drvdata(pdev);
 
+	clk_disable_unprepare(tmdev->ahb_clk);
 	clk_disable_unprepare(tmdev->bus_clk);
 	reset_control_assert(tmdev->reset);
 
-- 
2.17.1


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

* [PATCH v4 09/11] thermal: sun8i: rework for ths calibrate func
  2019-06-23 16:41 [PATCH v4 00/11] add thermal driver for h6 Yangtao Li
                   ` (7 preceding siblings ...)
  2019-06-23 16:42 ` [PATCH v4 08/11] thermal: sun8i: support ahb clocks Yangtao Li
@ 2019-06-23 16:42 ` Yangtao Li
  2019-06-23 16:42 ` [PATCH v4 10/11] dt-bindings: thermal: add binding document for h3 thermal controller Yangtao Li
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 21+ messages in thread
From: Yangtao Li @ 2019-06-23 16:42 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, davem, gregkh, mchehab+samsung,
	linus.walleij, nicolas.ferre, paulmck
  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 04f53ffb6a14..260b24340f5b 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:
@@ -251,7 +222,45 @@ static int sun50i_ths_calibrate(struct ths_device *tmdev)
 		}
 	}
 
-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;
@@ -300,7 +309,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 ahb_disable;
 
@@ -428,6 +437,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_thermal_init,
 	.irq_ack = sun50i_h6_irq_ack,
 };
-- 
2.17.1


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

* [PATCH v4 10/11] dt-bindings: thermal: add binding document for h3 thermal controller
  2019-06-23 16:41 [PATCH v4 00/11] add thermal driver for h6 Yangtao Li
                   ` (8 preceding siblings ...)
  2019-06-23 16:42 ` [PATCH v4 09/11] thermal: sun8i: rework for ths calibrate func Yangtao Li
@ 2019-06-23 16:42 ` Yangtao Li
  2019-06-24  8:50   ` Maxime Ripard
  2019-06-23 16:42 ` [PATCH v4 11/11] thermal: sun8i: add thermal driver for h3 Yangtao Li
  2019-07-10 23:09 ` [PATCH v4 00/11] add thermal driver for h6 Vasily Khoruzhick
  11 siblings, 1 reply; 21+ messages in thread
From: Yangtao Li @ 2019-06-23 16:42 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, davem, gregkh, mchehab+samsung,
	linus.walleij, nicolas.ferre, paulmck
  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       | 29 +++++++++++++++++--
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
index 2c5acc61ed03..1eaf68b5dd5a 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:
@@ -29,13 +30,22 @@ properties:
 
   clocks:
     minItems: 1
-    maxItems: 1
+    maxItems: 2
 
   clock-names:
-    const: bus
+    items:
+      - const: bus
+      - const: ahb
 
   '#thermal-sensor-cells':
-    const: 1
+    enum: [ 0, 1 ]
+    description: |
+      Definition depends on soc version:
+
+      For "allwinner,sun8i-h3-ths",
+      value must be 0.
+      For "allwinner,sun50i-h6-ths",
+      value must be 1.
 
   nvmem-cells:
     items:
@@ -55,6 +65,19 @@ required:
   - '#thermal-sensor-cells'
 
 examples:
+  - |
+    ths: ths@1c25000 {
+         compatible = "allwinner,sun8i-h3-ths";
+         reg = <0x01c25000 0x400>;
+         clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>;
+         clock-names = "bus", "ahb";
+         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>;
+    };
+
   - |
     ths: ths@5070400 {
          compatible = "allwinner,sun50i-h6-ths";
-- 
2.17.1


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

* [PATCH v4 11/11] thermal: sun8i: add thermal driver for h3
  2019-06-23 16:41 [PATCH v4 00/11] add thermal driver for h6 Yangtao Li
                   ` (9 preceding siblings ...)
  2019-06-23 16:42 ` [PATCH v4 10/11] dt-bindings: thermal: add binding document for h3 thermal controller Yangtao Li
@ 2019-06-23 16:42 ` Yangtao Li
  2019-06-24 12:05   ` Ondřej Jirman
  2019-07-10 23:09 ` [PATCH v4 00/11] add thermal driver for h6 Vasily Khoruzhick
  11 siblings, 1 reply; 21+ messages in thread
From: Yangtao Li @ 2019-06-23 16:42 UTC (permalink / raw)
  To: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, davem, gregkh, mchehab+samsung,
	linus.walleij, nicolas.ferre, paulmck
  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 | 72 +++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 260b24340f5b..c8ee291f3b17 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,9 @@
 #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 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 +132,21 @@ static const struct regmap_config config = {
 	.fast_io = true,
 };
 
+static int sun8i_h3_irq_ack(struct ths_device *tmdev)
+{
+	int state, ret = 0;
+
+	regmap_read(tmdev->regmap, SUN8I_THS_IS, &state);
+
+	if (state & BIT(8)) {
+		regmap_write(tmdev->regmap, SUN8I_THS_IS,
+			     BIT(8));
+		ret |= BIT(1);
+	}
+
+	return ret;
+}
+
 static int sun50i_h6_irq_ack(struct ths_device *tmdev)
 {
 	int i, state, ret = 0;
@@ -154,6 +180,14 @@ 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)
+{
+	regmap_write(tmdev->regmap, SUN8I_THS_TEMP_CALIB, *caldata);
+
+	return 0;
+}
+
 static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
 				   u16 *caldata, int callen)
 {
@@ -325,6 +359,32 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
 	return ret;
 }
 
+static int sun8i_h3_thermal_init(struct ths_device *tmdev)
+{
+	/* 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
+	 */
+	regmap_write(tmdev->regmap, SUN8I_THS_IC,
+		     SUN50I_H6_THS_PC_TEMP_PERIOD(58) | BIT(8));
+	/*
+	 * clkin = 24MHz
+	 * T acquire = clkin / (x + 1)
+	 *           = 20us
+	 * enable sensor
+	 */
+	regmap_write(tmdev->regmap, SUN8I_THS_CTRL0,
+		     SUN8I_THS_CTRL0_T_ACQ0(479));
+	regmap_write(tmdev->regmap, SUN8I_THS_CTRL2,
+		     SUN8I_THS_CTRL2_T_ACQ1(479) | BIT(0));
+
+	return 0;
+}
+
 static int sun50i_thermal_init(struct ths_device *tmdev)
 {
 	int val;
@@ -431,6 +491,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_ahb_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,
@@ -443,6 +514,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] 21+ messages in thread

* Re: [PATCH v4 02/11] dt-bindings: thermal: add binding document for h6 thermal controller
  2019-06-23 16:41 ` [PATCH v4 02/11] dt-bindings: thermal: add binding document for h6 thermal controller Yangtao Li
@ 2019-06-24  8:47   ` Maxime Ripard
  0 siblings, 0 replies; 21+ messages in thread
From: Maxime Ripard @ 2019-06-24  8:47 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	wens, davem, gregkh, mchehab+samsung, linus.walleij,
	nicolas.ferre, paulmck, linux-pm, devicetree, linux-arm-kernel,
	linux-kernel

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

Hi,

On Sun, Jun 23, 2019 at 12:41:57PM -0400, 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       | 71 +++++++++++++++++++
>  1 file changed, 71 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..2c5acc61ed03
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
> @@ -0,0 +1,71 @@
> +# 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:
> +    minItems: 1
> +    maxItems: 1

You can drop the minItems there

> +  nvmem-cells:
> +    items:
> +      - description: ths calibrate data
> +
> +  nvmem-cell-names:
> +    items:
> +      - const: calib

And for these two, you don't need the items either, it can be directly
const: calib (and the description for the first one).

> +required:
> +  - compatible
> +  - reg
> +  - reset
> +  - clocks
> +  - clock-names
> +  - interrupts
> +  - '#thermal-sensor-cells'
> +
> +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>;

Did you try to run make dtbs_check? That one will probably not
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] 21+ messages in thread

* Re: [PATCH v4 10/11] dt-bindings: thermal: add binding document for h3 thermal controller
  2019-06-23 16:42 ` [PATCH v4 10/11] dt-bindings: thermal: add binding document for h3 thermal controller Yangtao Li
@ 2019-06-24  8:50   ` Maxime Ripard
  0 siblings, 0 replies; 21+ messages in thread
From: Maxime Ripard @ 2019-06-24  8:50 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	wens, davem, gregkh, mchehab+samsung, linus.walleij,
	nicolas.ferre, paulmck, linux-pm, devicetree, linux-arm-kernel,
	linux-kernel

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

On Sun, Jun 23, 2019 at 12:42:05PM -0400, 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       | 29 +++++++++++++++++--
>  1 file changed, 26 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml b/Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
> index 2c5acc61ed03..1eaf68b5dd5a 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:
> @@ -29,13 +30,22 @@ properties:
>
>    clocks:
>      minItems: 1
> -    maxItems: 1
> +    maxItems: 2
>
>    clock-names:
> -    const: bus
> +    items:
> +      - const: bus
> +      - const: ahb

You need a min/maxItems here as well. Otherwise, on the H6, you will
have a warning since you asked for an array of two items, bus and ahb,
while you only have a single one.

>    '#thermal-sensor-cells':
> -    const: 1
> +    enum: [ 0, 1 ]
> +    description: |
> +      Definition depends on soc version:
> +
> +      For "allwinner,sun8i-h3-ths",
> +      value must be 0.
> +      For "allwinner,sun50i-h6-ths",
> +      value must be 1.

This must be checked using a conditional.

Something like:

if:
  properties:
    compatible:
      const: allwinner,sun8i-h3-ths

then:
  properties:
    "#thermal-sensor-cells":
      const: 0

else:
  properties:
    "#thermal-sensor-cells":
      const: 1

>    nvmem-cells:
>      items:
> @@ -55,6 +65,19 @@ required:
>    - '#thermal-sensor-cells'
>
>  examples:
> +  - |
> +    ths: ths@1c25000 {
> +         compatible = "allwinner,sun8i-h3-ths";
> +         reg = <0x01c25000 0x400>;
> +         clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_THS>;
> +         clock-names = "bus", "ahb";
> +         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>;
> +    };

Same remark here, it 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] 21+ messages in thread

* Re: [PATCH v4 11/11] thermal: sun8i: add thermal driver for h3
  2019-06-23 16:42 ` [PATCH v4 11/11] thermal: sun8i: add thermal driver for h3 Yangtao Li
@ 2019-06-24 12:05   ` Ondřej Jirman
  0 siblings, 0 replies; 21+ messages in thread
From: Ondřej Jirman @ 2019-06-24 12:05 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, davem, gregkh, mchehab+samsung,
	linus.walleij, nicolas.ferre, paulmck, devicetree, linux-kernel,
	linux-arm-kernel, linux-pm

Hello Yangtao,

On Sun, Jun 23, 2019 at 12:42:06PM -0400, Yangtao Li wrote:
> This patch adds the support for allwinner h3 thermal sensor.
> 
> Signed-off-by: Yangtao Li <tiny.windzz@gmail.com>
> ---
>  drivers/thermal/sun8i_thermal.c | 72 +++++++++++++++++++++++++++++++++
>  1 file changed, 72 insertions(+)
> 
> diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
> index 260b24340f5b..c8ee291f3b17 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,9 @@
>  #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 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 +132,21 @@ static const struct regmap_config config = {
>  	.fast_io = true,
>  };
>  
> +static int sun8i_h3_irq_ack(struct ths_device *tmdev)
> +{
> +	int state, ret = 0;
> +
> +	regmap_read(tmdev->regmap, SUN8I_THS_IS, &state);
> +
> +	if (state & BIT(8)) {
> +		regmap_write(tmdev->regmap, SUN8I_THS_IS,
> +			     BIT(8));
> +		ret |= BIT(1);
> +	}
> +
> +	return ret;
> +}
> +
>  static int sun50i_h6_irq_ack(struct ths_device *tmdev)
>  {
>  	int i, state, ret = 0;
> @@ -154,6 +180,14 @@ 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)
> +{
> +	regmap_write(tmdev->regmap, SUN8I_THS_TEMP_CALIB, *caldata);

You're missing a sanity check for callen here.

regards,
	o.

> +	return 0;
> +}
> +
>  static int sun50i_h6_ths_calibrate(struct ths_device *tmdev,
>  				   u16 *caldata, int callen)
>  {
> @@ -325,6 +359,32 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev)
>  	return ret;
>  }
>  
> +static int sun8i_h3_thermal_init(struct ths_device *tmdev)
> +{
> +	/* 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
> +	 */
> +	regmap_write(tmdev->regmap, SUN8I_THS_IC,
> +		     SUN50I_H6_THS_PC_TEMP_PERIOD(58) | BIT(8));
> +	/*
> +	 * clkin = 24MHz
> +	 * T acquire = clkin / (x + 1)
> +	 *           = 20us
> +	 * enable sensor
> +	 */
> +	regmap_write(tmdev->regmap, SUN8I_THS_CTRL0,
> +		     SUN8I_THS_CTRL0_T_ACQ0(479));
> +	regmap_write(tmdev->regmap, SUN8I_THS_CTRL2,
> +		     SUN8I_THS_CTRL2_T_ACQ1(479) | BIT(0));
> +
> +	return 0;
> +}
> +
>  static int sun50i_thermal_init(struct ths_device *tmdev)
>  {
>  	int val;
> @@ -431,6 +491,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_ahb_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,
> @@ -443,6 +514,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
> 
> 
> _______________________________________________
> 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] 21+ messages in thread

* Re: [PATCH v4 01/11] thermal: sun8i: add thermal driver for h6
  2019-06-23 16:41 ` [PATCH v4 01/11] thermal: sun8i: " Yangtao Li
@ 2019-06-24 12:07   ` Ondřej Jirman
  0 siblings, 0 replies; 21+ messages in thread
From: Ondřej Jirman @ 2019-06-24 12:07 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	maxime.ripard, wens, davem, gregkh, mchehab+samsung,
	linus.walleij, nicolas.ferre, paulmck, devicetree, linux-kernel,
	linux-arm-kernel, linux-pm

Hello Yangtao,

On Sun, Jun 23, 2019 at 12:41:56PM -0400, 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 | 405 ++++++++++++++++++++++++++++++++
>  4 files changed, 427 insertions(+)
>  create mode 100644 drivers/thermal/sun8i_thermal.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 36a84614d6c3..67e7fcfaded2 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -674,6 +674,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..d6918c62682b
> --- /dev/null
> +++ b/drivers/thermal/sun8i_thermal.c
> @@ -0,0 +1,405 @@
> +// 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 -EBUSY;

You should return -EAGAIN here to avoid the warning (failed to read out thermal
zone (%d)) if you believe this error is temporary.

regards,
	o.

> +	*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, calib_offest;
> +
> +		/*
> +		 * 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;
> +		}
> +
> +		calib_offest = SUN50I_H6_THS_TEMP_CALIB + (i / 2) * 0x4;
> +
> +		if (i % 2) {
> +			int val;
> +
> +			regmap_read(tmdev->regmap, calib_offest, &val);
> +			val = (val & TEMP_CALIB_MASK) | (cdata << 16);
> +			regmap_write(tmdev->regmap, calib_offest, val);
> +		} else {
> +			regmap_write(tmdev->regmap, calib_offest, cdata);
> +		}
> +	}
> +
> +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_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_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] 21+ messages in thread

* Re: [PATCH v4 08/11] thermal: sun8i: support ahb clocks
  2019-06-23 16:42 ` [PATCH v4 08/11] thermal: sun8i: support ahb clocks Yangtao Li
@ 2019-06-24 18:23   ` Maxime Ripard
  2019-06-25  0:34     ` Ondřej Jirman
  0 siblings, 1 reply; 21+ messages in thread
From: Maxime Ripard @ 2019-06-24 18:23 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, edubezval, daniel.lezcano, robh+dt, mark.rutland,
	wens, davem, gregkh, mchehab+samsung, linus.walleij,
	nicolas.ferre, paulmck, linux-pm, devicetree, linux-arm-kernel,
	linux-kernel

On Sun, Jun 23, 2019 at 12:42:03PM -0400, Yangtao Li 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 ed1c19bb27cf..04f53ffb6a14 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_ahb_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                              *ahb_clk;

Hmm, thinking a bit about this, the name of those two clocks doesn't
make sense. AHB is the bus being used to access that device, so the
bus clock is the AHB clock.

What is that clock being used for?

Maxime

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

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

* Re: [PATCH v4 08/11] thermal: sun8i: support ahb clocks
  2019-06-24 18:23   ` Maxime Ripard
@ 2019-06-25  0:34     ` Ondřej Jirman
  2019-06-25  8:25       ` Maxime Ripard
  0 siblings, 1 reply; 21+ messages in thread
From: Ondřej Jirman @ 2019-06-25  0:34 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Yangtao Li, mark.rutland, devicetree, linux-pm, gregkh,
	linus.walleij, daniel.lezcano, linux-kernel, edubezval, wens,
	robh+dt, mchehab+samsung, rui.zhang, paulmck, davem,
	linux-arm-kernel

On Mon, Jun 24, 2019 at 08:23:33PM +0200, Maxime Ripard wrote:
> On Sun, Jun 23, 2019 at 12:42:03PM -0400, Yangtao Li 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 ed1c19bb27cf..04f53ffb6a14 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_ahb_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                              *ahb_clk;
> 
> Hmm, thinking a bit about this, the name of those two clocks doesn't
> make sense. AHB is the bus being used to access that device, so the
> bus clock is the AHB clock.
> 
> What is that clock being used for?

To control the A/D and sample averaging logic, I suppose. It's controlled by the
THS_CLK_REG (THS Clock Register) in H3 user manual.

bus_clk controls THS_GATING in BUS_CLK_GATING_REG2 (THS module is connected to
APB bus).

I'd call it ths_clk and bus_clk.

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] 21+ messages in thread

* Re: [PATCH v4 08/11] thermal: sun8i: support ahb clocks
  2019-06-25  0:34     ` Ondřej Jirman
@ 2019-06-25  8:25       ` Maxime Ripard
  0 siblings, 0 replies; 21+ messages in thread
From: Maxime Ripard @ 2019-06-25  8:25 UTC (permalink / raw)
  To: Yangtao Li, mark.rutland, devicetree, linux-pm, gregkh,
	linus.walleij, daniel.lezcano, linux-kernel, edubezval, wens,
	robh+dt, mchehab+samsung, rui.zhang, paulmck, davem,
	linux-arm-kernel

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

On Tue, Jun 25, 2019 at 02:34:16AM +0200, Ondřej Jirman wrote:
> On Mon, Jun 24, 2019 at 08:23:33PM +0200, Maxime Ripard wrote:
> > On Sun, Jun 23, 2019 at 12:42:03PM -0400, Yangtao Li 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 ed1c19bb27cf..04f53ffb6a14 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_ahb_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                              *ahb_clk;
> >
> > Hmm, thinking a bit about this, the name of those two clocks doesn't
> > make sense. AHB is the bus being used to access that device, so the
> > bus clock is the AHB clock.
> >
> > What is that clock being used for?
>
> To control the A/D and sample averaging logic, I suppose. It's controlled by the
> THS_CLK_REG (THS Clock Register) in H3 user manual.
>
> bus_clk controls THS_GATING in BUS_CLK_GATING_REG2 (THS module is connected to
> APB bus).
>
> I'd call it ths_clk and bus_clk.

Thanks. We've tried to make clock names a bit more generic and
consistent, so let's use mod instead.

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] 21+ messages in thread

* Re: [PATCH v4 00/11] add thermal driver for h6
  2019-06-23 16:41 [PATCH v4 00/11] add thermal driver for h6 Yangtao Li
                   ` (10 preceding siblings ...)
  2019-06-23 16:42 ` [PATCH v4 11/11] thermal: sun8i: add thermal driver for h3 Yangtao Li
@ 2019-07-10 23:09 ` Vasily Khoruzhick
  2019-07-13 18:01   ` Vasily Khoruzhick
  11 siblings, 1 reply; 21+ messages in thread
From: Vasily Khoruzhick @ 2019-07-10 23:09 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, Eduardo Valentin, Daniel Lezcano, Rob Herring,
	Mark Rutland, Maxime Ripard, Chen-Yu Tsai, David S. Miller,
	Greg Kroah-Hartman, Mauro Carvalho Chehab, Linus Walleij,
	Nicolas Ferre, paulmck, devicetree, linux-kernel, arm-linux,
	Linux PM

On Sun, Jun 23, 2019 at 9:42 AM Yangtao Li <tiny.windzz@gmail.com> wrote:
>
> This patchset add support for H3 and H6 thermal sensor.
>
> BTY, do a cleanup in thermal makfile.
>
> Yangtao Li (11):
>   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 ahb 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

It would be nice to add dts changes to this series. It's unlikely that
you'll get any "Tested-by" otherwise.


>  .../bindings/thermal/sun8i-thermal.yaml       |  94 +++
>  MAINTAINERS                                   |   7 +
>  drivers/thermal/Kconfig                       |  14 +
>  drivers/thermal/Makefile                      |   9 +-
>  drivers/thermal/sun8i_thermal.c               | 534 ++++++++++++++++++
>  5 files changed, 654 insertions(+), 4 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
>  create mode 100644 drivers/thermal/sun8i_thermal.c
>
> ---
> v4:
> -add h3 support
> -fix yaml file
> ---
> 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] 21+ messages in thread

* Re: [PATCH v4 00/11] add thermal driver for h6
  2019-07-10 23:09 ` [PATCH v4 00/11] add thermal driver for h6 Vasily Khoruzhick
@ 2019-07-13 18:01   ` Vasily Khoruzhick
  0 siblings, 0 replies; 21+ messages in thread
From: Vasily Khoruzhick @ 2019-07-13 18:01 UTC (permalink / raw)
  To: Yangtao Li
  Cc: rui.zhang, Eduardo Valentin, Daniel Lezcano, Rob Herring,
	Mark Rutland, Maxime Ripard, Chen-Yu Tsai, David S. Miller,
	Greg Kroah-Hartman, Mauro Carvalho Chehab, Linus Walleij,
	Nicolas Ferre, paulmck, devicetree, linux-kernel, arm-linux,
	Linux PM

On Wed, Jul 10, 2019 at 4:09 PM Vasily Khoruzhick <anarsoul@gmail.com> wrote:
>
> On Sun, Jun 23, 2019 at 9:42 AM Yangtao Li <tiny.windzz@gmail.com> wrote:
> >
> > This patchset add support for H3 and H6 thermal sensor.
> >
> > BTY, do a cleanup in thermal makfile.
> >
> > Yangtao Li (11):
> >   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 ahb 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
>
> It would be nice to add dts changes to this series. It's unlikely that
> you'll get any "Tested-by" otherwise.

I added A64 support on top of this series, see
https://github.com/anarsoul/linux-2.6/tree/v5.2-thermal

Branch also contains patches to enable DVFS on A64, feel free to
cherry pick only those related to thermal driver if you want to
include A64 support into v5 series.

>
> >  .../bindings/thermal/sun8i-thermal.yaml       |  94 +++
> >  MAINTAINERS                                   |   7 +
> >  drivers/thermal/Kconfig                       |  14 +
> >  drivers/thermal/Makefile                      |   9 +-
> >  drivers/thermal/sun8i_thermal.c               | 534 ++++++++++++++++++
> >  5 files changed, 654 insertions(+), 4 deletions(-)
> >  create mode 100644 Documentation/devicetree/bindings/thermal/sun8i-thermal.yaml
> >  create mode 100644 drivers/thermal/sun8i_thermal.c
> >
> > ---
> > v4:
> > -add h3 support
> > -fix yaml file
> > ---
> > 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] 21+ messages in thread

end of thread, back to index

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-23 16:41 [PATCH v4 00/11] add thermal driver for h6 Yangtao Li
2019-06-23 16:41 ` [PATCH v4 01/11] thermal: sun8i: " Yangtao Li
2019-06-24 12:07   ` Ondřej Jirman
2019-06-23 16:41 ` [PATCH v4 02/11] dt-bindings: thermal: add binding document for h6 thermal controller Yangtao Li
2019-06-24  8:47   ` Maxime Ripard
2019-06-23 16:41 ` [PATCH v4 03/11] thermal: fix indentation in makefile Yangtao Li
2019-06-23 16:41 ` [PATCH v4 04/11] thermal: sun8i: get ths sensor number from device compatible Yangtao Li
2019-06-23 16:42 ` [PATCH v4 05/11] thermal: sun8i: rework for sun8i_ths_get_temp() Yangtao Li
2019-06-23 16:42 ` [PATCH v4 06/11] thermal: sun8i: get ths init func from device compatible Yangtao Li
2019-06-23 16:42 ` [PATCH v4 07/11] thermal: sun8i: rework for ths irq handler func Yangtao Li
2019-06-23 16:42 ` [PATCH v4 08/11] thermal: sun8i: support ahb clocks Yangtao Li
2019-06-24 18:23   ` Maxime Ripard
2019-06-25  0:34     ` Ondřej Jirman
2019-06-25  8:25       ` Maxime Ripard
2019-06-23 16:42 ` [PATCH v4 09/11] thermal: sun8i: rework for ths calibrate func Yangtao Li
2019-06-23 16:42 ` [PATCH v4 10/11] dt-bindings: thermal: add binding document for h3 thermal controller Yangtao Li
2019-06-24  8:50   ` Maxime Ripard
2019-06-23 16:42 ` [PATCH v4 11/11] thermal: sun8i: add thermal driver for h3 Yangtao Li
2019-06-24 12:05   ` Ondřej Jirman
2019-07-10 23:09 ` [PATCH v4 00/11] add thermal driver for h6 Vasily Khoruzhick
2019-07-13 18:01   ` Vasily Khoruzhick

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


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