This adds documentation of device tree bindings for the
thermal sensor controller of hi3660 SoC.
Signed-off-by: Tao Wang <[email protected]>
---
.../devicetree/bindings/thermal/hi3660-thermal.txt | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
diff --git a/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt b/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
new file mode 100644
index 0000000..c034670
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
@@ -0,0 +1,17 @@
+* Temperature Sensor on hisilicon hi3660 SoC
+
+** Required properties :
+
+- compatible: "hisilicon,thermal-hi3660".
+- reg: physical base address of thermal sensor and length of memory mapped
+ region.
+- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description.
+
+Example :
+
+ tsensor: tsensor {
+ compatible = "hisilicon,thermal-hi3660";
+ reg = <0x0 0xfff30000 0x0 0x1000>;
+ #thermal-sensor-cells = <1>;
+ status = "ok";
+ };
--
1.7.9.5
This patch adds the support for thermal sensor of Hi3660 SoC.
this will register sensors for thermal framework and use device
tree to bind cooling device.
Signed-off-by: Tao Wang <[email protected]>
Signed-off-by: Leo Yan <[email protected]>
---
drivers/thermal/Kconfig | 10 ++
drivers/thermal/Makefile | 1 +
drivers/thermal/hi3660_thermal.c | 198 ++++++++++++++++++++++++++++++++++++++
3 files changed, 209 insertions(+)
create mode 100644 drivers/thermal/hi3660_thermal.c
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index b5b5fac..3e7fa95 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -203,6 +203,16 @@ config HISI_THERMAL
thermal framework. cpufreq is used as the cooling device to throttle
CPUs when the passive trip is crossed.
+config HI3660_THERMAL
+ tristate "Hi3660 thermal driver"
+ depends on ARCH_HISI || COMPILE_TEST
+ depends on HAS_IOMEM
+ depends on OF
+ default y
+ help
+ Enable this to plug Hi3660 thermal driver into the Linux thermal
+ framework.
+
config IMX_THERMAL
tristate "Temperature sensor driver for Freescale i.MX SoCs"
depends on (ARCH_MXC && CPU_THERMAL) || COMPILE_TEST
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 094d703..f29d0a5 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
obj-$(CONFIG_ST_THERMAL) += st/
obj-$(CONFIG_QCOM_TSENS) += qcom/
obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
+obj-$(CONFIG_HI3660_THERMAL) += hi3660_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
diff --git a/drivers/thermal/hi3660_thermal.c b/drivers/thermal/hi3660_thermal.c
new file mode 100644
index 0000000..a538721
--- /dev/null
+++ b/drivers/thermal/hi3660_thermal.c
@@ -0,0 +1,198 @@
+/*
+ * linux/drivers/thermal/hi3660_thermal.c
+ *
+ * Copyright (c) 2017 Hisilicon Limited.
+ * Copyright (c) 2017 Linaro Limited.
+ *
+ * Author: Tao Wang <[email protected]>
+ * Author: Leo Yan <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/thermal.h>
+
+#include "thermal_core.h"
+
+#define HW_MAX_SENSORS 4
+#define HISI_MAX_SENSORS 6
+#define SENSOR_MAX 4
+#define SENSOR_AVG 5
+
+#define ADC_MIN 116
+#define ADC_MAX 922
+
+/* hi3660 Thermal Sensor Dev Structure */
+struct hi3660_thermal_sensor {
+ struct hi3660_thermal_data *thermal;
+ struct thermal_zone_device *tzd;
+
+ uint32_t id;
+};
+
+struct hi3660_thermal_data {
+ struct platform_device *pdev;
+ struct hi3660_thermal_sensor sensors[HISI_MAX_SENSORS];
+ void __iomem *thermal_base;
+};
+
+unsigned int sensor_reg_offset[HW_MAX_SENSORS] = { 0x1c, 0x5c, 0x9c, 0xdc };
+
+
+static int hi3660_thermal_get_temp(void *_sensor, int *temp)
+{
+ struct hi3660_thermal_sensor *sensor = _sensor;
+ struct hi3660_thermal_data *data = sensor->thermal;
+ unsigned int idx;
+ int val, average = 0, max = 0;
+
+ if (sensor->id < HW_MAX_SENSORS) {
+ val = readl(data->thermal_base + sensor_reg_offset[sensor->id]);
+ val = clamp_val(val, ADC_MIN, ADC_MAX);
+ } else {
+ for (idx = 0; idx < HW_MAX_SENSORS; idx++) {
+ val = readl(data->thermal_base
+ + sensor_reg_offset[idx]);
+ val = clamp_val(val, ADC_MIN, ADC_MAX);
+ average += val;
+ if (val > max)
+ max = val;
+ }
+
+ if (sensor->id == SENSOR_MAX)
+ val = max;
+ else if (sensor->id == SENSOR_AVG)
+ val = average / HW_MAX_SENSORS;
+ }
+
+ *temp = ((val - ADC_MIN) * 165000) / (ADC_MAX - ADC_MIN) - 40000;
+
+ return 0;
+}
+
+static struct thermal_zone_of_device_ops hi3660_of_thermal_ops = {
+ .get_temp = hi3660_thermal_get_temp,
+};
+
+static int hi3660_thermal_register_sensor(struct platform_device *pdev,
+ struct hi3660_thermal_data *data,
+ struct hi3660_thermal_sensor *sensor,
+ int index)
+{
+ int ret = 0;
+
+ sensor->id = index;
+ sensor->thermal = data;
+
+ sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev,
+ sensor->id, sensor, &hi3660_of_thermal_ops);
+ if (IS_ERR(sensor->tzd)) {
+ ret = PTR_ERR(sensor->tzd);
+ sensor->tzd = NULL;
+ }
+
+ return ret;
+}
+
+static void hi3660_thermal_toggle_sensor(struct hi3660_thermal_sensor *sensor,
+ bool on)
+{
+ struct thermal_zone_device *tzd = sensor->tzd;
+
+ tzd->ops->set_mode(tzd,
+ on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);
+}
+
+static int hi3660_thermal_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct hi3660_thermal_data *data;
+ struct resource *res;
+ int ret = 0;
+ int i;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->pdev = pdev;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data->thermal_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(data->thermal_base)) {
+ dev_err(dev, "failed get reg base\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, data);
+
+ for (i = 0; i < HISI_MAX_SENSORS; ++i) {
+ ret = hi3660_thermal_register_sensor(pdev, data,
+ &data->sensors[i], i);
+ if (ret)
+ dev_err(&pdev->dev,
+ "failed to register thermal sensor%d: %d\n",
+ i, ret);
+ else
+ hi3660_thermal_toggle_sensor(&data->sensors[i], true);
+ }
+
+ dev_info(&pdev->dev, "Thermal Sensor Loaded\n");
+ return 0;
+}
+
+static int hi3660_thermal_exit(struct platform_device *pdev)
+{
+ struct hi3660_thermal_data *data = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < HISI_MAX_SENSORS; i++) {
+ struct hi3660_thermal_sensor *sensor = &data->sensors[i];
+
+ if (!sensor->tzd)
+ continue;
+
+ hi3660_thermal_toggle_sensor(sensor, false);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id hi3660_thermal_id_table[] = {
+ { .compatible = "hisilicon,thermal-hi3660" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, hi3660_thermal_id_table);
+
+static struct platform_driver hi3660_thermal_driver = {
+ .probe = hi3660_thermal_probe,
+ .remove = hi3660_thermal_exit,
+ .driver = {
+ .name = "hi3660_thermal",
+ .of_match_table = hi3660_thermal_id_table,
+ },
+};
+
+module_platform_driver(hi3660_thermal_driver);
+
+MODULE_AUTHOR("Tao Wang <[email protected]>");
+MODULE_AUTHOR("Leo Yan <[email protected]>");
+MODULE_DESCRIPTION("hi3660 thermal driver");
+MODULE_LICENSE("GPL v2");
--
1.7.9.5
Bind thermal sensor driver for Hi3660.
Signed-off-by: Tao Wang <[email protected]>
Signed-off-by: Leo Yan <[email protected]>
---
arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index 3983086..cc67958 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -156,5 +156,12 @@
clock-names = "uartclk", "apb_pclk";
status = "disabled";
};
+
+ tsensor: tsensor {
+ compatible = "hisilicon,thermal-hi3660";
+ reg = <0x0 0xfff30000 0x0 0x1000>;
+ #thermal-sensor-cells = <1>;
+ status = "ok";
+ };
};
};
--
1.7.9.5
在 2017/6/20 15:38, Guodong Xu 写道:
>
>
> 2017年6月20日 上午11:49,"Tao Wang" <[email protected] <mailto:[email protected]>>写道:
>
> Bind thermal sensor driver for Hi3660.
>
> Signed-off-by: Tao Wang <[email protected] <mailto:[email protected]>>
> Signed-off-by: Leo Yan <[email protected] <mailto:[email protected]>>
> ---
> arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> index 3983086..cc67958 100644
> --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> @@ -156,5 +156,12 @@
>
>
> i am wondering which tree this patch should be applied to. Actually Olof Johansson [email protected] <mailto:[email protected]> just merged hi3660 dts into his tree. You should better rebase you dts patch onto that.
Can you share me the git path?
>
>
> clock-names = "uartclk", "apb_pclk";
> status = "disabled";
> };
> +
> + tsensor: tsensor {
> + compatible = "hisilicon,thermal-hi3660";
> + reg = <0x0 0xfff30000 0x0 0x1000>;
> + #thermal-sensor-cells = <1>;
> + status = "ok";
>
>
> please remove status ok. that's default. redundant.
ok
>
> + };
> };
> };
> --
> 1.7.9.5
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected] <mailto:[email protected]>
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>
>
>
Hi Tao,
On 2017/6/20 4:40, Tao Wang wrote:
> This adds documentation of device tree bindings for the
> thermal sensor controller of hi3660 SoC.
>
> Signed-off-by: Tao Wang <[email protected]>
> ---
> .../devicetree/bindings/thermal/hi3660-thermal.txt | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
>
> diff --git a/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt b/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
> new file mode 100644
> index 0000000..c034670
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
> @@ -0,0 +1,17 @@
> +* Temperature Sensor on hisilicon hi3660 SoC
> +
> +** Required properties :
> +
> +- compatible: "hisilicon,thermal-hi3660".
It is better to put the SoC name before the function string.
BR,
Wei
> +- reg: physical base address of thermal sensor and length of memory mapped
> + region.
> +- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description.
> +
> +Example :
> +
> + tsensor: tsensor {
> + compatible = "hisilicon,thermal-hi3660";
> + reg = <0x0 0xfff30000 0x0 0x1000>;
> + #thermal-sensor-cells = <1>;
> + status = "ok";
> + };
>
Hi Tao Wang,
On 2017/6/20 4:40, Tao Wang wrote:
> This patch adds the support for thermal sensor of Hi3660 SoC.
> this will register sensors for thermal framework and use device
> tree to bind cooling device.
>
> Signed-off-by: Tao Wang <[email protected]>
> Signed-off-by: Leo Yan <[email protected]>
> ---
> drivers/thermal/Kconfig | 10 ++
> drivers/thermal/Makefile | 1 +
> drivers/thermal/hi3660_thermal.c | 198 ++++++++++++++++++++++++++++++++++++++
> 3 files changed, 209 insertions(+)
> create mode 100644 drivers/thermal/hi3660_thermal.c
>
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index b5b5fac..3e7fa95 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -203,6 +203,16 @@ config HISI_THERMAL
> thermal framework. cpufreq is used as the cooling device to throttle
> CPUs when the passive trip is crossed.
>
> +config HI3660_THERMAL
Please keep alphabet order and swap the order
between HI3660_THERMAL and HISI_THERMAL.
Thanks!
BR,
Wei
> + tristate "Hi3660 thermal driver"
> + depends on ARCH_HISI || COMPILE_TEST
> + depends on HAS_IOMEM
> + depends on OF
> + default y
> + help
> + Enable this to plug Hi3660 thermal driver into the Linux thermal
> + framework.
> +
> config IMX_THERMAL
> tristate "Temperature sensor driver for Freescale i.MX SoCs"
> depends on (ARCH_MXC && CPU_THERMAL) || COMPILE_TEST
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 094d703..f29d0a5 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -55,6 +55,7 @@ obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
> obj-$(CONFIG_ST_THERMAL) += st/
> obj-$(CONFIG_QCOM_TSENS) += qcom/
> obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
> +obj-$(CONFIG_HI3660_THERMAL) += hi3660_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
> diff --git a/drivers/thermal/hi3660_thermal.c b/drivers/thermal/hi3660_thermal.c
> new file mode 100644
> index 0000000..a538721
> --- /dev/null
> +++ b/drivers/thermal/hi3660_thermal.c
> @@ -0,0 +1,198 @@
> +/*
> + * linux/drivers/thermal/hi3660_thermal.c
> + *
> + * Copyright (c) 2017 Hisilicon Limited.
> + * Copyright (c) 2017 Linaro Limited.
> + *
> + * Author: Tao Wang <[email protected]>
> + * Author: Leo Yan <[email protected]>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/of.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/thermal.h>
> +
> +#include "thermal_core.h"
> +
> +#define HW_MAX_SENSORS 4
> +#define HISI_MAX_SENSORS 6
> +#define SENSOR_MAX 4
> +#define SENSOR_AVG 5
> +
> +#define ADC_MIN 116
> +#define ADC_MAX 922
> +
> +/* hi3660 Thermal Sensor Dev Structure */
> +struct hi3660_thermal_sensor {
> + struct hi3660_thermal_data *thermal;
> + struct thermal_zone_device *tzd;
> +
> + uint32_t id;
> +};
> +
> +struct hi3660_thermal_data {
> + struct platform_device *pdev;
> + struct hi3660_thermal_sensor sensors[HISI_MAX_SENSORS];
> + void __iomem *thermal_base;
> +};
> +
> +unsigned int sensor_reg_offset[HW_MAX_SENSORS] = { 0x1c, 0x5c, 0x9c, 0xdc };
> +
> +
> +static int hi3660_thermal_get_temp(void *_sensor, int *temp)
> +{
> + struct hi3660_thermal_sensor *sensor = _sensor;
> + struct hi3660_thermal_data *data = sensor->thermal;
> + unsigned int idx;
> + int val, average = 0, max = 0;
> +
> + if (sensor->id < HW_MAX_SENSORS) {
> + val = readl(data->thermal_base + sensor_reg_offset[sensor->id]);
> + val = clamp_val(val, ADC_MIN, ADC_MAX);
> + } else {
> + for (idx = 0; idx < HW_MAX_SENSORS; idx++) {
> + val = readl(data->thermal_base
> + + sensor_reg_offset[idx]);
> + val = clamp_val(val, ADC_MIN, ADC_MAX);
> + average += val;
> + if (val > max)
> + max = val;
> + }
> +
> + if (sensor->id == SENSOR_MAX)
> + val = max;
> + else if (sensor->id == SENSOR_AVG)
> + val = average / HW_MAX_SENSORS;
> + }
> +
> + *temp = ((val - ADC_MIN) * 165000) / (ADC_MAX - ADC_MIN) - 40000;
> +
> + return 0;
> +}
> +
> +static struct thermal_zone_of_device_ops hi3660_of_thermal_ops = {
> + .get_temp = hi3660_thermal_get_temp,
> +};
> +
> +static int hi3660_thermal_register_sensor(struct platform_device *pdev,
> + struct hi3660_thermal_data *data,
> + struct hi3660_thermal_sensor *sensor,
> + int index)
> +{
> + int ret = 0;
> +
> + sensor->id = index;
> + sensor->thermal = data;
> +
> + sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev,
> + sensor->id, sensor, &hi3660_of_thermal_ops);
> + if (IS_ERR(sensor->tzd)) {
> + ret = PTR_ERR(sensor->tzd);
> + sensor->tzd = NULL;
> + }
> +
> + return ret;
> +}
> +
> +static void hi3660_thermal_toggle_sensor(struct hi3660_thermal_sensor *sensor,
> + bool on)
> +{
> + struct thermal_zone_device *tzd = sensor->tzd;
> +
> + tzd->ops->set_mode(tzd,
> + on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);
> +}
> +
> +static int hi3660_thermal_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct hi3660_thermal_data *data;
> + struct resource *res;
> + int ret = 0;
> + int i;
> +
> + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> +
> + data->pdev = pdev;
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + data->thermal_base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(data->thermal_base)) {
> + dev_err(dev, "failed get reg base\n");
> + return -ENOMEM;
> + }
> +
> + platform_set_drvdata(pdev, data);
> +
> + for (i = 0; i < HISI_MAX_SENSORS; ++i) {
> + ret = hi3660_thermal_register_sensor(pdev, data,
> + &data->sensors[i], i);
> + if (ret)
> + dev_err(&pdev->dev,
> + "failed to register thermal sensor%d: %d\n",
> + i, ret);
> + else
> + hi3660_thermal_toggle_sensor(&data->sensors[i], true);
> + }
> +
> + dev_info(&pdev->dev, "Thermal Sensor Loaded\n");
> + return 0;
> +}
> +
> +static int hi3660_thermal_exit(struct platform_device *pdev)
> +{
> + struct hi3660_thermal_data *data = platform_get_drvdata(pdev);
> + int i;
> +
> + for (i = 0; i < HISI_MAX_SENSORS; i++) {
> + struct hi3660_thermal_sensor *sensor = &data->sensors[i];
> +
> + if (!sensor->tzd)
> + continue;
> +
> + hi3660_thermal_toggle_sensor(sensor, false);
> + }
> +
> + return 0;
> +}
> +
> +static const struct of_device_id hi3660_thermal_id_table[] = {
> + { .compatible = "hisilicon,thermal-hi3660" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, hi3660_thermal_id_table);
> +
> +static struct platform_driver hi3660_thermal_driver = {
> + .probe = hi3660_thermal_probe,
> + .remove = hi3660_thermal_exit,
> + .driver = {
> + .name = "hi3660_thermal",
> + .of_match_table = hi3660_thermal_id_table,
> + },
> +};
> +
> +module_platform_driver(hi3660_thermal_driver);
> +
> +MODULE_AUTHOR("Tao Wang <[email protected]>");
> +MODULE_AUTHOR("Leo Yan <[email protected]>");
> +MODULE_DESCRIPTION("hi3660 thermal driver");
> +MODULE_LICENSE("GPL v2");
>
On Tue, Jun 20, 2017 at 4:32 PM, Wangtao (Kevin, Kirin)
<[email protected]> wrote:
>
>
> 在 2017/6/20 15:38, Guodong Xu 写道:
>>
>>
>>
>> 2017年6月20日 上午11:49,"Tao Wang" <[email protected]
>> <mailto:[email protected]>>写道:
>>
>> Bind thermal sensor driver for Hi3660.
>>
>> Signed-off-by: Tao Wang <[email protected]
>> <mailto:[email protected]>>
>> Signed-off-by: Leo Yan <[email protected]
>> <mailto:[email protected]>>
>> ---
>> arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 7 +++++++
>> 1 file changed, 7 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
>> b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
>> index 3983086..cc67958 100644
>> --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
>> +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
>> @@ -156,5 +156,12 @@
>>
>>
>> i am wondering which tree this patch should be applied to. Actually Olof
>> Johansson [email protected] <mailto:[email protected]> just merged hi3660 dts into
>> his tree. You should better rebase you dts patch onto that.
>
> Can you share me the git path?
As of this morning, it has shown up in linux next tag: next-20170620
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/arch/arm64/boot/dts/hisilicon?h=next-20170620
-Guodong
>>
>>
>>
>> clock-names = "uartclk", "apb_pclk";
>> status = "disabled";
>> };
>> +
>> + tsensor: tsensor {
>> + compatible = "hisilicon,thermal-hi3660";
>> + reg = <0x0 0xfff30000 0x0 0x1000>;
>> + #thermal-sensor-cells = <1>;
>> + status = "ok";
>>
>>
>> please remove status ok. that's default. redundant.
>
> ok
>>
>>
>> + };
>> };
>> };
>> --
>> 1.7.9.5
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> [email protected]
>> <mailto:[email protected]>
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>> <http://lists.infradead.org/mailman/listinfo/linux-arm-kernel>
>>
>>
>
e( 2017/6/20 18:27, Wei Xu ei:
> Hi Tao,
>
> On 2017/6/20 4:40, Tao Wang wrote:
>> This adds documentation of device tree bindings for the
>> thermal sensor controller of hi3660 SoC.
>>
>> Signed-off-by: Tao Wang <[email protected]>
>> ---
>> .../devicetree/bindings/thermal/hi3660-thermal.txt | 17 +++++++++++++++++
>> 1 file changed, 17 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
>>
>> diff --git a/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt b/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
>> new file mode 100644
>> index 0000000..c034670
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
>> @@ -0,0 +1,17 @@
>> +* Temperature Sensor on hisilicon hi3660 SoC
>> +
>> +** Required properties :
>> +
>> +- compatible: "hisilicon,thermal-hi3660".
>
> It is better to put the SoC name before the function string.
ok, I will fix it, thank you.
>
> BR,
> Wei
>
>> +- reg: physical base address of thermal sensor and length of memory mapped
>> + region.
>> +- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description.
>> +
>> +Example :
>> +
>> + tsensor: tsensor {
>> + compatible = "hisilicon,thermal-hi3660";
>> + reg = <0x0 0xfff30000 0x0 0x1000>;
>> + #thermal-sensor-cells = <1>;
>> + status = "ok";
>> + };
>>
>
>
> .
>
e( 2017/6/20 18:31, Wei Xu ei:
> Hi Tao Wang,
>
> On 2017/6/20 4:40, Tao Wang wrote:
>> This patch adds the support for thermal sensor of Hi3660 SoC.
>> this will register sensors for thermal framework and use device
>> tree to bind cooling device.
>>
>> Signed-off-by: Tao Wang <[email protected]>
>> Signed-off-by: Leo Yan <[email protected]>
>> ---
>> drivers/thermal/Kconfig | 10 ++
>> drivers/thermal/Makefile | 1 +
>> drivers/thermal/hi3660_thermal.c | 198 ++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 209 insertions(+)
>> create mode 100644 drivers/thermal/hi3660_thermal.c
>>
>> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
>> index b5b5fac..3e7fa95 100644
>> --- a/drivers/thermal/Kconfig
>> +++ b/drivers/thermal/Kconfig
>> @@ -203,6 +203,16 @@ config HISI_THERMAL
>> thermal framework. cpufreq is used as the cooling device to throttle
>> CPUs when the passive trip is crossed.
>>
>> +config HI3660_THERMAL
>
> Please keep alphabet order and swap the order
> between HI3660_THERMAL and HISI_THERMAL.
OK
>
> Thanks!
>
> BR,
> Wei
>
>> + tristate "Hi3660 thermal driver"
>> + depends on ARCH_HISI || COMPILE_TEST
>> + depends on HAS_IOMEM
>> + depends on OF
>> + default y
>> + help
>> + Enable this to plug Hi3660 thermal driver into the Linux thermal
>> + framework.
>> +
>> config IMX_THERMAL
>> tristate "Temperature sensor driver for Freescale i.MX SoCs"
>> depends on (ARCH_MXC && CPU_THERMAL) || COMPILE_TEST
>> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
>> index 094d703..f29d0a5 100644
>> --- a/drivers/thermal/Makefile
>> +++ b/drivers/thermal/Makefile
>> @@ -55,6 +55,7 @@ obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
>> obj-$(CONFIG_ST_THERMAL) += st/
>> obj-$(CONFIG_QCOM_TSENS) += qcom/
>> obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
>> +obj-$(CONFIG_HI3660_THERMAL) += hi3660_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
>> diff --git a/drivers/thermal/hi3660_thermal.c b/drivers/thermal/hi3660_thermal.c
>> new file mode 100644
>> index 0000000..a538721
>> --- /dev/null
>> +++ b/drivers/thermal/hi3660_thermal.c
>> @@ -0,0 +1,198 @@
>> +/*
>> + * linux/drivers/thermal/hi3660_thermal.c
>> + *
>> + * Copyright (c) 2017 Hisilicon Limited.
>> + * Copyright (c) 2017 Linaro Limited.
>> + *
>> + * Author: Tao Wang <[email protected]>
>> + * Author: Leo Yan <[email protected]>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; version 2 of the License.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/device.h>
>> +#include <linux/err.h>
>> +#include <linux/io.h>
>> +#include <linux/kernel.h>
>> +#include <linux/of.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/thermal.h>
>> +
>> +#include "thermal_core.h"
>> +
>> +#define HW_MAX_SENSORS 4
>> +#define HISI_MAX_SENSORS 6
>> +#define SENSOR_MAX 4
>> +#define SENSOR_AVG 5
>> +
>> +#define ADC_MIN 116
>> +#define ADC_MAX 922
>> +
>> +/* hi3660 Thermal Sensor Dev Structure */
>> +struct hi3660_thermal_sensor {
>> + struct hi3660_thermal_data *thermal;
>> + struct thermal_zone_device *tzd;
>> +
>> + uint32_t id;
>> +};
>> +
>> +struct hi3660_thermal_data {
>> + struct platform_device *pdev;
>> + struct hi3660_thermal_sensor sensors[HISI_MAX_SENSORS];
>> + void __iomem *thermal_base;
>> +};
>> +
>> +unsigned int sensor_reg_offset[HW_MAX_SENSORS] = { 0x1c, 0x5c, 0x9c, 0xdc };
>> +
>> +
>> +static int hi3660_thermal_get_temp(void *_sensor, int *temp)
>> +{
>> + struct hi3660_thermal_sensor *sensor = _sensor;
>> + struct hi3660_thermal_data *data = sensor->thermal;
>> + unsigned int idx;
>> + int val, average = 0, max = 0;
>> +
>> + if (sensor->id < HW_MAX_SENSORS) {
>> + val = readl(data->thermal_base + sensor_reg_offset[sensor->id]);
>> + val = clamp_val(val, ADC_MIN, ADC_MAX);
>> + } else {
>> + for (idx = 0; idx < HW_MAX_SENSORS; idx++) {
>> + val = readl(data->thermal_base
>> + + sensor_reg_offset[idx]);
>> + val = clamp_val(val, ADC_MIN, ADC_MAX);
>> + average += val;
>> + if (val > max)
>> + max = val;
>> + }
>> +
>> + if (sensor->id == SENSOR_MAX)
>> + val = max;
>> + else if (sensor->id == SENSOR_AVG)
>> + val = average / HW_MAX_SENSORS;
>> + }
>> +
>> + *temp = ((val - ADC_MIN) * 165000) / (ADC_MAX - ADC_MIN) - 40000;
>> +
>> + return 0;
>> +}
>> +
>> +static struct thermal_zone_of_device_ops hi3660_of_thermal_ops = {
>> + .get_temp = hi3660_thermal_get_temp,
>> +};
>> +
>> +static int hi3660_thermal_register_sensor(struct platform_device *pdev,
>> + struct hi3660_thermal_data *data,
>> + struct hi3660_thermal_sensor *sensor,
>> + int index)
>> +{
>> + int ret = 0;
>> +
>> + sensor->id = index;
>> + sensor->thermal = data;
>> +
>> + sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev,
>> + sensor->id, sensor, &hi3660_of_thermal_ops);
>> + if (IS_ERR(sensor->tzd)) {
>> + ret = PTR_ERR(sensor->tzd);
>> + sensor->tzd = NULL;
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static void hi3660_thermal_toggle_sensor(struct hi3660_thermal_sensor *sensor,
>> + bool on)
>> +{
>> + struct thermal_zone_device *tzd = sensor->tzd;
>> +
>> + tzd->ops->set_mode(tzd,
>> + on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);
>> +}
>> +
>> +static int hi3660_thermal_probe(struct platform_device *pdev)
>> +{
>> + struct device *dev = &pdev->dev;
>> + struct hi3660_thermal_data *data;
>> + struct resource *res;
>> + int ret = 0;
>> + int i;
>> +
>> + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
>> + if (!data)
>> + return -ENOMEM;
>> +
>> + data->pdev = pdev;
>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + data->thermal_base = devm_ioremap_resource(dev, res);
>> + if (IS_ERR(data->thermal_base)) {
>> + dev_err(dev, "failed get reg base\n");
>> + return -ENOMEM;
>> + }
>> +
>> + platform_set_drvdata(pdev, data);
>> +
>> + for (i = 0; i < HISI_MAX_SENSORS; ++i) {
>> + ret = hi3660_thermal_register_sensor(pdev, data,
>> + &data->sensors[i], i);
>> + if (ret)
>> + dev_err(&pdev->dev,
>> + "failed to register thermal sensor%d: %d\n",
>> + i, ret);
>> + else
>> + hi3660_thermal_toggle_sensor(&data->sensors[i], true);
>> + }
>> +
>> + dev_info(&pdev->dev, "Thermal Sensor Loaded\n");
>> + return 0;
>> +}
>> +
>> +static int hi3660_thermal_exit(struct platform_device *pdev)
>> +{
>> + struct hi3660_thermal_data *data = platform_get_drvdata(pdev);
>> + int i;
>> +
>> + for (i = 0; i < HISI_MAX_SENSORS; i++) {
>> + struct hi3660_thermal_sensor *sensor = &data->sensors[i];
>> +
>> + if (!sensor->tzd)
>> + continue;
>> +
>> + hi3660_thermal_toggle_sensor(sensor, false);
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static const struct of_device_id hi3660_thermal_id_table[] = {
>> + { .compatible = "hisilicon,thermal-hi3660" },
>> + {}
>> +};
>> +MODULE_DEVICE_TABLE(of, hi3660_thermal_id_table);
>> +
>> +static struct platform_driver hi3660_thermal_driver = {
>> + .probe = hi3660_thermal_probe,
>> + .remove = hi3660_thermal_exit,
>> + .driver = {
>> + .name = "hi3660_thermal",
>> + .of_match_table = hi3660_thermal_id_table,
>> + },
>> +};
>> +
>> +module_platform_driver(hi3660_thermal_driver);
>> +
>> +MODULE_AUTHOR("Tao Wang <[email protected]>");
>> +MODULE_AUTHOR("Leo Yan <[email protected]>");
>> +MODULE_DESCRIPTION("hi3660 thermal driver");
>> +MODULE_LICENSE("GPL v2");
>>
>
>
> .
>
Hi Rui, Eduardo,
On Tue, Jun 20, 2017 at 11:40:34AM +0800, Tao Wang wrote:
[...]
> diff --git a/drivers/thermal/hi3660_thermal.c b/drivers/thermal/hi3660_thermal.c
> new file mode 100644
> index 0000000..a538721
> --- /dev/null
> +++ b/drivers/thermal/hi3660_thermal.c
> @@ -0,0 +1,198 @@
> +/*
> + * linux/drivers/thermal/hi3660_thermal.c
> + *
> + * Copyright (c) 2017 Hisilicon Limited.
> + * Copyright (c) 2017 Linaro Limited.
> + *
> + * Author: Tao Wang <[email protected]>
> + * Author: Leo Yan <[email protected]>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/of.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/thermal.h>
> +
> +#include "thermal_core.h"
> +
> +#define HW_MAX_SENSORS 4
> +#define HISI_MAX_SENSORS 6
> +#define SENSOR_MAX 4
> +#define SENSOR_AVG 5
> +
> +#define ADC_MIN 116
> +#define ADC_MAX 922
> +
> +/* hi3660 Thermal Sensor Dev Structure */
> +struct hi3660_thermal_sensor {
> + struct hi3660_thermal_data *thermal;
> + struct thermal_zone_device *tzd;
> +
> + uint32_t id;
> +};
> +
> +struct hi3660_thermal_data {
> + struct platform_device *pdev;
> + struct hi3660_thermal_sensor sensors[HISI_MAX_SENSORS];
> + void __iomem *thermal_base;
> +};
> +
> +unsigned int sensor_reg_offset[HW_MAX_SENSORS] = { 0x1c, 0x5c, 0x9c, 0xdc };
> +
> +
> +static int hi3660_thermal_get_temp(void *_sensor, int *temp)
> +{
> + struct hi3660_thermal_sensor *sensor = _sensor;
> + struct hi3660_thermal_data *data = sensor->thermal;
> + unsigned int idx;
> + int val, average = 0, max = 0;
> +
> + if (sensor->id < HW_MAX_SENSORS) {
> + val = readl(data->thermal_base + sensor_reg_offset[sensor->id]);
> + val = clamp_val(val, ADC_MIN, ADC_MAX);
> + } else {
> + for (idx = 0; idx < HW_MAX_SENSORS; idx++) {
> + val = readl(data->thermal_base
> + + sensor_reg_offset[idx]);
> + val = clamp_val(val, ADC_MIN, ADC_MAX);
> + average += val;
> + if (val > max)
> + max = val;
> + }
> +
> + if (sensor->id == SENSOR_MAX)
> + val = max;
> + else if (sensor->id == SENSOR_AVG)
> + val = average / HW_MAX_SENSORS;
> + }
I think here have one thing it's better to check with you ahead and
want your suggestions.
Tao adds two 'software' sensors, one is sensor 4 which is used to
present the maximum temperature value crossing from sensor 0 ~ 3; and
another sensor 4 is used to present the average temperature value.
Does this make sense for you?
> + *temp = ((val - ADC_MIN) * 165000) / (ADC_MAX - ADC_MIN) - 40000;
> +
> + return 0;
> +}
> +
> +static struct thermal_zone_of_device_ops hi3660_of_thermal_ops = {
> + .get_temp = hi3660_thermal_get_temp,
> +};
> +
> +static int hi3660_thermal_register_sensor(struct platform_device *pdev,
> + struct hi3660_thermal_data *data,
> + struct hi3660_thermal_sensor *sensor,
> + int index)
> +{
> + int ret = 0;
> +
> + sensor->id = index;
> + sensor->thermal = data;
> +
> + sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev,
> + sensor->id, sensor, &hi3660_of_thermal_ops);
> + if (IS_ERR(sensor->tzd)) {
> + ret = PTR_ERR(sensor->tzd);
> + sensor->tzd = NULL;
> + }
> +
> + return ret;
> +}
> +
> +static void hi3660_thermal_toggle_sensor(struct hi3660_thermal_sensor *sensor,
> + bool on)
> +{
> + struct thermal_zone_device *tzd = sensor->tzd;
> +
> + tzd->ops->set_mode(tzd,
> + on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);
> +}
> +
> +static int hi3660_thermal_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct hi3660_thermal_data *data;
> + struct resource *res;
> + int ret = 0;
> + int i;
> +
> + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> +
> + data->pdev = pdev;
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + data->thermal_base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(data->thermal_base)) {
> + dev_err(dev, "failed get reg base\n");
> + return -ENOMEM;
> + }
> +
> + platform_set_drvdata(pdev, data);
> +
> + for (i = 0; i < HISI_MAX_SENSORS; ++i) {
> + ret = hi3660_thermal_register_sensor(pdev, data,
> + &data->sensors[i], i);
> + if (ret)
> + dev_err(&pdev->dev,
> + "failed to register thermal sensor%d: %d\n",
> + i, ret);
> + else
> + hi3660_thermal_toggle_sensor(&data->sensors[i], true);
> + }
> +
> + dev_info(&pdev->dev, "Thermal Sensor Loaded\n");
> + return 0;
> +}
> +
> +static int hi3660_thermal_exit(struct platform_device *pdev)
> +{
> + struct hi3660_thermal_data *data = platform_get_drvdata(pdev);
> + int i;
> +
> + for (i = 0; i < HISI_MAX_SENSORS; i++) {
> + struct hi3660_thermal_sensor *sensor = &data->sensors[i];
> +
> + if (!sensor->tzd)
> + continue;
> +
> + hi3660_thermal_toggle_sensor(sensor, false);
> + }
> +
> + return 0;
> +}
> +
> +static const struct of_device_id hi3660_thermal_id_table[] = {
> + { .compatible = "hisilicon,thermal-hi3660" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, hi3660_thermal_id_table);
> +
> +static struct platform_driver hi3660_thermal_driver = {
> + .probe = hi3660_thermal_probe,
> + .remove = hi3660_thermal_exit,
> + .driver = {
> + .name = "hi3660_thermal",
> + .of_match_table = hi3660_thermal_id_table,
> + },
> +};
> +
> +module_platform_driver(hi3660_thermal_driver);
> +
> +MODULE_AUTHOR("Tao Wang <[email protected]>");
> +MODULE_AUTHOR("Leo Yan <[email protected]>");
> +MODULE_DESCRIPTION("hi3660 thermal driver");
> +MODULE_LICENSE("GPL v2");
> --
> 1.7.9.5
>
This adds documentation of device tree bindings for the
thermal sensor controller of hi3660 SoC.
Signed-off-by: Tao Wang <[email protected]>
---
Changes in v2:
- remove redundant property
.../devicetree/bindings/thermal/hi3660-thermal.txt | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
diff --git a/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt b/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
new file mode 100644
index 0000000..f3dddcf
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
@@ -0,0 +1,16 @@
+* Temperature Sensor on hisilicon hi3660 SoC
+
+** Required properties :
+
+- compatible: "hisilicon,thermal-hi3660".
+- reg: physical base address of thermal sensor and length of memory mapped
+ region.
+- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description.
+
+Example :
+
+ tsensor: tsensor {
+ compatible = "hisilicon,thermal-hi3660";
+ reg = <0x0 0xfff30000 0x0 0x1000>;
+ #thermal-sensor-cells = <1>;
+ };
--
1.7.9.5
This patch adds the support for thermal sensor of Hi3660 SoC.
this will register sensors for thermal framework and use device
tree to bind cooling device.
Signed-off-by: Tao Wang <[email protected]>
Signed-off-by: Leo Yan <[email protected]>
---
Changes in v2:
- correct alphabet order
- correct compatible name
drivers/thermal/Kconfig | 10 ++
drivers/thermal/Makefile | 1 +
drivers/thermal/hi3660_thermal.c | 198 ++++++++++++++++++++++++++++++++++++++
3 files changed, 209 insertions(+)
create mode 100644 drivers/thermal/hi3660_thermal.c
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index b5b5fac..ed22a90 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -192,6 +192,16 @@ config THERMAL_EMULATION
because userland can easily disable the thermal policy by simply
flooding this sysfs node with low temperature values.
+config HI3660_THERMAL
+ tristate "Hi3660 thermal driver"
+ depends on ARCH_HISI || COMPILE_TEST
+ depends on HAS_IOMEM
+ depends on OF
+ default y
+ help
+ Enable this to plug Hi3660 thermal driver into the Linux thermal
+ framework.
+
config HISI_THERMAL
tristate "Hisilicon thermal driver"
depends on ARCH_HISI || COMPILE_TEST
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 094d703..f29d0a5 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
obj-$(CONFIG_ST_THERMAL) += st/
obj-$(CONFIG_QCOM_TSENS) += qcom/
obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
+obj-$(CONFIG_HI3660_THERMAL) += hi3660_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
diff --git a/drivers/thermal/hi3660_thermal.c b/drivers/thermal/hi3660_thermal.c
new file mode 100644
index 0000000..68fa9018
--- /dev/null
+++ b/drivers/thermal/hi3660_thermal.c
@@ -0,0 +1,198 @@
+/*
+ * linux/drivers/thermal/hi3660_thermal.c
+ *
+ * Copyright (c) 2017 Hisilicon Limited.
+ * Copyright (c) 2017 Linaro Limited.
+ *
+ * Author: Tao Wang <[email protected]>
+ * Author: Leo Yan <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/thermal.h>
+
+#include "thermal_core.h"
+
+#define HW_MAX_SENSORS 4
+#define HISI_MAX_SENSORS 6
+#define SENSOR_MAX 4
+#define SENSOR_AVG 5
+
+#define ADC_MIN 116
+#define ADC_MAX 922
+
+/* hi3660 Thermal Sensor Dev Structure */
+struct hi3660_thermal_sensor {
+ struct hi3660_thermal_data *thermal;
+ struct thermal_zone_device *tzd;
+
+ uint32_t id;
+};
+
+struct hi3660_thermal_data {
+ struct platform_device *pdev;
+ struct hi3660_thermal_sensor sensors[HISI_MAX_SENSORS];
+ void __iomem *thermal_base;
+};
+
+unsigned int sensor_reg_offset[HW_MAX_SENSORS] = { 0x1c, 0x5c, 0x9c, 0xdc };
+
+
+static int hi3660_thermal_get_temp(void *_sensor, int *temp)
+{
+ struct hi3660_thermal_sensor *sensor = _sensor;
+ struct hi3660_thermal_data *data = sensor->thermal;
+ unsigned int idx;
+ int val, average = 0, max = 0;
+
+ if (sensor->id < HW_MAX_SENSORS) {
+ val = readl(data->thermal_base + sensor_reg_offset[sensor->id]);
+ val = clamp_val(val, ADC_MIN, ADC_MAX);
+ } else {
+ for (idx = 0; idx < HW_MAX_SENSORS; idx++) {
+ val = readl(data->thermal_base
+ + sensor_reg_offset[idx]);
+ val = clamp_val(val, ADC_MIN, ADC_MAX);
+ average += val;
+ if (val > max)
+ max = val;
+ }
+
+ if (sensor->id == SENSOR_MAX)
+ val = max;
+ else if (sensor->id == SENSOR_AVG)
+ val = average / HW_MAX_SENSORS;
+ }
+
+ *temp = ((val - ADC_MIN) * 165000) / (ADC_MAX - ADC_MIN) - 40000;
+
+ return 0;
+}
+
+static struct thermal_zone_of_device_ops hi3660_of_thermal_ops = {
+ .get_temp = hi3660_thermal_get_temp,
+};
+
+static int hi3660_thermal_register_sensor(struct platform_device *pdev,
+ struct hi3660_thermal_data *data,
+ struct hi3660_thermal_sensor *sensor,
+ int index)
+{
+ int ret = 0;
+
+ sensor->id = index;
+ sensor->thermal = data;
+
+ sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev,
+ sensor->id, sensor, &hi3660_of_thermal_ops);
+ if (IS_ERR(sensor->tzd)) {
+ ret = PTR_ERR(sensor->tzd);
+ sensor->tzd = NULL;
+ }
+
+ return ret;
+}
+
+static void hi3660_thermal_toggle_sensor(struct hi3660_thermal_sensor *sensor,
+ bool on)
+{
+ struct thermal_zone_device *tzd = sensor->tzd;
+
+ tzd->ops->set_mode(tzd,
+ on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);
+}
+
+static int hi3660_thermal_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct hi3660_thermal_data *data;
+ struct resource *res;
+ int ret = 0;
+ int i;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->pdev = pdev;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data->thermal_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(data->thermal_base)) {
+ dev_err(dev, "failed get reg base\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, data);
+
+ for (i = 0; i < HISI_MAX_SENSORS; ++i) {
+ ret = hi3660_thermal_register_sensor(pdev, data,
+ &data->sensors[i], i);
+ if (ret)
+ dev_err(&pdev->dev,
+ "failed to register thermal sensor%d: %d\n",
+ i, ret);
+ else
+ hi3660_thermal_toggle_sensor(&data->sensors[i], true);
+ }
+
+ dev_info(&pdev->dev, "Thermal Sensor Loaded\n");
+ return 0;
+}
+
+static int hi3660_thermal_exit(struct platform_device *pdev)
+{
+ struct hi3660_thermal_data *data = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < HISI_MAX_SENSORS; i++) {
+ struct hi3660_thermal_sensor *sensor = &data->sensors[i];
+
+ if (!sensor->tzd)
+ continue;
+
+ hi3660_thermal_toggle_sensor(sensor, false);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id hi3660_thermal_id_table[] = {
+ { .compatible = "hisilicon,hi3660-thermal" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, hi3660_thermal_id_table);
+
+static struct platform_driver hi3660_thermal_driver = {
+ .probe = hi3660_thermal_probe,
+ .remove = hi3660_thermal_exit,
+ .driver = {
+ .name = "hi3660_thermal",
+ .of_match_table = hi3660_thermal_id_table,
+ },
+};
+
+module_platform_driver(hi3660_thermal_driver);
+
+MODULE_AUTHOR("Tao Wang <[email protected]>");
+MODULE_AUTHOR("Leo Yan <[email protected]>");
+MODULE_DESCRIPTION("hi3660 thermal driver");
+MODULE_LICENSE("GPL v2");
--
1.7.9.5
Bind thermal sensor driver for Hi3660.
Signed-off-by: Tao Wang <[email protected]>
Signed-off-by: Leo Yan <[email protected]>
---
Changes in v2:
- rebase changes on linux next
arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index c6a1961..a6a1e01 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -848,5 +848,11 @@
&sdio_cfg_func>;
status = "disabled";
};
+
+ tsensor: tsensor {
+ compatible = "hisilicon,hi3660-thermal";
+ reg = <0x0 0xfff30000 0x0 0x1000>;
+ #thermal-sensor-cells = <1>;
+ };
};
};
--
1.7.9.5
Hey Tao,
On Thu, Jun 22, 2017 at 11:42:02AM +0800, Tao Wang wrote:
> This patch adds the support for thermal sensor of Hi3660 SoC.
> this will register sensors for thermal framework and use device
> tree to bind cooling device.
>
> Signed-off-by: Tao Wang <[email protected]>
> Signed-off-by: Leo Yan <[email protected]>
> ---
> Changes in v2:
> - correct alphabet order
> - correct compatible name
>
> drivers/thermal/Kconfig | 10 ++
> drivers/thermal/Makefile | 1 +
> drivers/thermal/hi3660_thermal.c | 198 ++++++++++++++++++++++++++++++++++++++
> 3 files changed, 209 insertions(+)
> create mode 100644 drivers/thermal/hi3660_thermal.c
>
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index b5b5fac..ed22a90 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -192,6 +192,16 @@ config THERMAL_EMULATION
> because userland can easily disable the thermal policy by simply
> flooding this sysfs node with low temperature values.
>
> +config HI3660_THERMAL
> + tristate "Hi3660 thermal driver"
> + depends on ARCH_HISI || COMPILE_TEST
> + depends on HAS_IOMEM
> + depends on OF
> + default y
> + help
> + Enable this to plug Hi3660 thermal driver into the Linux thermal
> + framework.
> +
> config HISI_THERMAL
> tristate "Hisilicon thermal driver"
> depends on ARCH_HISI || COMPILE_TEST
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 094d703..f29d0a5 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -55,6 +55,7 @@ obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
> obj-$(CONFIG_ST_THERMAL) += st/
> obj-$(CONFIG_QCOM_TSENS) += qcom/
> obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
> +obj-$(CONFIG_HI3660_THERMAL) += hi3660_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
> diff --git a/drivers/thermal/hi3660_thermal.c b/drivers/thermal/hi3660_thermal.c
> new file mode 100644
> index 0000000..68fa9018
> --- /dev/null
> +++ b/drivers/thermal/hi3660_thermal.c
> @@ -0,0 +1,198 @@
> +/*
> + * linux/drivers/thermal/hi3660_thermal.c
> + *
> + * Copyright (c) 2017 Hisilicon Limited.
> + * Copyright (c) 2017 Linaro Limited.
> + *
> + * Author: Tao Wang <[email protected]>
> + * Author: Leo Yan <[email protected]>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/of.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/thermal.h>
> +
> +#include "thermal_core.h"
> +
> +#define HW_MAX_SENSORS 4
> +#define HISI_MAX_SENSORS 6
> +#define SENSOR_MAX 4
> +#define SENSOR_AVG 5
> +
> +#define ADC_MIN 116
> +#define ADC_MAX 922
> +
> +/* hi3660 Thermal Sensor Dev Structure */
> +struct hi3660_thermal_sensor {
> + struct hi3660_thermal_data *thermal;
> + struct thermal_zone_device *tzd;
> +
> + uint32_t id;
> +};
> +
> +struct hi3660_thermal_data {
> + struct platform_device *pdev;
> + struct hi3660_thermal_sensor sensors[HISI_MAX_SENSORS];
> + void __iomem *thermal_base;
> +};
> +
> +unsigned int sensor_reg_offset[HW_MAX_SENSORS] = { 0x1c, 0x5c, 0x9c, 0xdc };
> +
> +
> +static int hi3660_thermal_get_temp(void *_sensor, int *temp)
> +{
> + struct hi3660_thermal_sensor *sensor = _sensor;
> + struct hi3660_thermal_data *data = sensor->thermal;
> + unsigned int idx;
> + int val, average = 0, max = 0;
> +
> + if (sensor->id < HW_MAX_SENSORS) {
> + val = readl(data->thermal_base + sensor_reg_offset[sensor->id]);
> + val = clamp_val(val, ADC_MIN, ADC_MAX);
> + } else {
> + for (idx = 0; idx < HW_MAX_SENSORS; idx++) {
> + val = readl(data->thermal_base
> + + sensor_reg_offset[idx]);
> + val = clamp_val(val, ADC_MIN, ADC_MAX);
> + average += val;
> + if (val > max)
> + max = val;
> + }
> +
> + if (sensor->id == SENSOR_MAX)
> + val = max;
> + else if (sensor->id == SENSOR_AVG)
> + val = average / HW_MAX_SENSORS;
> + }
> +
> + *temp = ((val - ADC_MIN) * 165000) / (ADC_MAX - ADC_MIN) - 40000;
Where do these constants come from (165000 and 40000) can these some how
be rearranged and described in DT (coefficients) and using the offset and slope fields?
> +
> + return 0;
> +}
> +
> +static struct thermal_zone_of_device_ops hi3660_of_thermal_ops = {
> + .get_temp = hi3660_thermal_get_temp,
> +};
> +
> +static int hi3660_thermal_register_sensor(struct platform_device *pdev,
> + struct hi3660_thermal_data *data,
> + struct hi3660_thermal_sensor *sensor,
> + int index)
> +{
> + int ret = 0;
> +
> + sensor->id = index;
> + sensor->thermal = data;
> +
> + sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev,
> + sensor->id, sensor, &hi3660_of_thermal_ops);
> + if (IS_ERR(sensor->tzd)) {
> + ret = PTR_ERR(sensor->tzd);
> + sensor->tzd = NULL;
> + }
> +
> + return ret;
> +}
> +
> +static void hi3660_thermal_toggle_sensor(struct hi3660_thermal_sensor *sensor,
> + bool on)
> +{
> + struct thermal_zone_device *tzd = sensor->tzd;
> +
> + tzd->ops->set_mode(tzd,
> + on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);
> +}
> +
> +static int hi3660_thermal_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct hi3660_thermal_data *data;
> + struct resource *res;
> + int ret = 0;
> + int i;
> +
> + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> +
> + data->pdev = pdev;
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + data->thermal_base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(data->thermal_base)) {
> + dev_err(dev, "failed get reg base\n");
> + return -ENOMEM;
> + }
> +
> + platform_set_drvdata(pdev, data);
> +
> + for (i = 0; i < HISI_MAX_SENSORS; ++i) {
> + ret = hi3660_thermal_register_sensor(pdev, data,
> + &data->sensors[i], i);
> + if (ret)
> + dev_err(&pdev->dev,
> + "failed to register thermal sensor%d: %d\n",
> + i, ret);
Do you really want to continue if some of the sensors fail to register?
> + else
> + hi3660_thermal_toggle_sensor(&data->sensors[i], true);
> + }
> +
> + dev_info(&pdev->dev, "Thermal Sensor Loaded\n");
Do you really need the above info in the kernel log?
> + return 0;
> +}
> +
> +static int hi3660_thermal_exit(struct platform_device *pdev)
> +{
> + struct hi3660_thermal_data *data = platform_get_drvdata(pdev);
> + int i;
> +
> + for (i = 0; i < HISI_MAX_SENSORS; i++) {
> + struct hi3660_thermal_sensor *sensor = &data->sensors[i];
> +
> + if (!sensor->tzd)
> + continue;
Why are you considering a valid case of not registering all expected
sensors?
> +
> + hi3660_thermal_toggle_sensor(sensor, false);
> + }
> +
> + return 0;
> +}
> +
> +static const struct of_device_id hi3660_thermal_id_table[] = {
> + { .compatible = "hisilicon,hi3660-thermal" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, hi3660_thermal_id_table);
> +
> +static struct platform_driver hi3660_thermal_driver = {
> + .probe = hi3660_thermal_probe,
> + .remove = hi3660_thermal_exit,
> + .driver = {
> + .name = "hi3660_thermal",
> + .of_match_table = hi3660_thermal_id_table,
> + },
> +};
> +
> +module_platform_driver(hi3660_thermal_driver);
> +
> +MODULE_AUTHOR("Tao Wang <[email protected]>");
> +MODULE_AUTHOR("Leo Yan <[email protected]>");
> +MODULE_DESCRIPTION("hi3660 thermal driver");
> +MODULE_LICENSE("GPL v2");
> --
> 1.7.9.5
>
On Thu, Jun 22, 2017 at 11:42:01AM +0800, Tao Wang wrote:
> This adds documentation of device tree bindings for the
> thermal sensor controller of hi3660 SoC.
>
> Signed-off-by: Tao Wang <[email protected]>
> ---
> Changes in v2:
> - remove redundant property
>
> .../devicetree/bindings/thermal/hi3660-thermal.txt | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
>
> diff --git a/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt b/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
> new file mode 100644
> index 0000000..f3dddcf
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
> @@ -0,0 +1,16 @@
> +* Temperature Sensor on hisilicon hi3660 SoC
> +
Would you mind add some more description of the sensors/where to find
further hardware documentation?
> +** Required properties :
> +
> +- compatible: "hisilicon,thermal-hi3660".
> +- reg: physical base address of thermal sensor and length of memory mapped
> + region.
> +- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description.
> +
> +Example :
> +
> + tsensor: tsensor {
> + compatible = "hisilicon,thermal-hi3660";
> + reg = <0x0 0xfff30000 0x0 0x1000>;
> + #thermal-sensor-cells = <1>;
> + };
> --
> 1.7.9.5
>
On Thu, Jun 22, 2017 at 11:42:03AM +0800, Tao Wang wrote:
> Bind thermal sensor driver for Hi3660.
>
> Signed-off-by: Tao Wang <[email protected]>
> Signed-off-by: Leo Yan <[email protected]>
> ---
> Changes in v2:
> - rebase changes on linux next
>
> arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> index c6a1961..a6a1e01 100644
> --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> @@ -848,5 +848,11 @@
> &sdio_cfg_func>;
> status = "disabled";
> };
> +
> + tsensor: tsensor {
> + compatible = "hisilicon,hi3660-thermal";
> + reg = <0x0 0xfff30000 0x0 0x1000>;
> + #thermal-sensor-cells = <1>;
> + };
Are you planning to also add thermal zone entries?
> };
> };
> --
> 1.7.9.5
>
On 2017/7/1 11:06, "Eduardo Valentin" <[email protected]> wrote:>
> On Thu, Jun 22, 2017 at 11:42:03AM +0800, Tao Wang wrote:
> > Bind thermal sensor driver for Hi3660.
> >
> > Signed-off-by: Tao Wang <[email protected]>
> > Signed-off-by: Leo Yan <[email protected]>
> > ---
> > Changes in v2:
> > - rebase changes on linux next
> >
> > arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 6 ++++++
> > 1 file changed, 6 insertions(+)
> >
> > diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> > index c6a1961..a6a1e01 100644
> > --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> > +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> > @@ -848,5 +848,11 @@
> > &sdio_cfg_func>;
> > status = "disabled";
> > };
> > +
> > + tsensor: tsensor {
> > + compatible = "hisilicon,hi3660-thermal";
> > + reg = <0x0 0xfff30000 0x0 0x1000>;
> > + #thermal-sensor-cells = <1>;
> > + };
>
> Are you planning to also add thermal zone entries?
Yes, after cpufreq enabled.
>
> > };
> > };
> > --
> > 1.7.9.5
> >
On 2017/7/1 11:06, "Eduardo Valentin" <[email protected]> wrote:
>
> On Thu, Jun 22, 2017 at 11:42:01AM +0800, Tao Wang wrote:
> > This adds documentation of device tree bindings for the
> > thermal sensor controller of hi3660 SoC.
> >
> > Signed-off-by: Tao Wang <[email protected]>
> > ---
> > Changes in v2:
> > - remove redundant property
> >
> > .../devicetree/bindings/thermal/hi3660-thermal.txt | 16
> ++++++++++++++++
> > 1 file changed, 16 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/thermal/hi3660-
> thermal.txt
> >
> > diff --git a/Documentation/devicetree/bindings/thermal/hi3660-
> thermal.txt b/Documentation/devicetree/bindings/thermal/hi3660-
> thermal.txt
> > new file mode 100644
> > index 0000000..f3dddcf
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/thermal/hi3660-thermal.txt
> > @@ -0,0 +1,16 @@
> > +* Temperature Sensor on hisilicon hi3660 SoC
> > +
>
> Would you mind add some more description of the sensors/where to find
> further hardware documentation?
Sure, documentation is on
https://github.com/96boards/documentation/blob/master/ConsumerEdition/HiKey960/HardwareDocs/HiKey960_SoC_Reference_Manual.pdf
>
> > +** Required properties :
> > +
> > +- compatible: "hisilicon,thermal-hi3660".
> > +- reg: physical base address of thermal sensor and length of memory
> mapped
> > + region.
> > +- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description.
> > +
> > +Example :
> > +
> > + tsensor: tsensor {
> > + compatible = "hisilicon,thermal-hi3660";
> > + reg = <0x0 0xfff30000 0x0 0x1000>;
> > + #thermal-sensor-cells = <1>;
> > + };
> > --
> > 1.7.9.5
> >
On 2017/7/1 11:06, "Eduardo Valentin" <[email protected]> wrote:>
> Hey Tao,
>
> On Thu, Jun 22, 2017 at 11:42:02AM +0800, Tao Wang wrote:
> > This patch adds the support for thermal sensor of Hi3660 SoC.
> > this will register sensors for thermal framework and use device
> > tree to bind cooling device.
> >
> > Signed-off-by: Tao Wang <[email protected]>
> > Signed-off-by: Leo Yan <[email protected]>
> > ---
> > Changes in v2:
> > - correct alphabet order
> > - correct compatible name
> >
> > drivers/thermal/Kconfig | 10 ++
> > drivers/thermal/Makefile | 1 +
> > drivers/thermal/hi3660_thermal.c | 198
> ++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 209 insertions(+)
> > create mode 100644 drivers/thermal/hi3660_thermal.c
> >
> > diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> > index b5b5fac..ed22a90 100644
> > --- a/drivers/thermal/Kconfig
> > +++ b/drivers/thermal/Kconfig
> > @@ -192,6 +192,16 @@ config THERMAL_EMULATION
> > because userland can easily disable the thermal policy by simply
> > flooding this sysfs node with low temperature values.
> >
> > +config HI3660_THERMAL
> > + tristate "Hi3660 thermal driver"
> > + depends on ARCH_HISI || COMPILE_TEST
> > + depends on HAS_IOMEM
> > + depends on OF
> > + default y
> > + help
> > + Enable this to plug Hi3660 thermal driver into the Linux thermal
> > + framework.
> > +
> > config HISI_THERMAL
> > tristate "Hisilicon thermal driver"
> > depends on ARCH_HISI || COMPILE_TEST
> > diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> > index 094d703..f29d0a5 100644
> > --- a/drivers/thermal/Makefile
> > +++ b/drivers/thermal/Makefile
> > @@ -55,6 +55,7 @@ obj-$(CONFIG_INTEL_PCH_THERMAL) +=
> intel_pch_thermal.o
> > obj-$(CONFIG_ST_THERMAL) += st/
> > obj-$(CONFIG_QCOM_TSENS) += qcom/
> > obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
> > +obj-$(CONFIG_HI3660_THERMAL) += hi3660_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
> > diff --git a/drivers/thermal/hi3660_thermal.c
> b/drivers/thermal/hi3660_thermal.c
> > new file mode 100644
> > index 0000000..68fa9018
> > --- /dev/null
> > +++ b/drivers/thermal/hi3660_thermal.c
> > @@ -0,0 +1,198 @@
> > +/*
> > + * linux/drivers/thermal/hi3660_thermal.c
> > + *
> > + * Copyright (c) 2017 Hisilicon Limited.
> > + * Copyright (c) 2017 Linaro Limited.
> > + *
> > + * Author: Tao Wang <[email protected]>
> > + * Author: Leo Yan <[email protected]>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License as published by
> > + * the Free Software Foundation; version 2 of the License.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/device.h>
> > +#include <linux/err.h>
> > +#include <linux/io.h>
> > +#include <linux/kernel.h>
> > +#include <linux/of.h>
> > +#include <linux/module.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/thermal.h>
> > +
> > +#include "thermal_core.h"
> > +
> > +#define HW_MAX_SENSORS 4
> > +#define HISI_MAX_SENSORS 6
> > +#define SENSOR_MAX 4
> > +#define SENSOR_AVG 5
> > +
> > +#define ADC_MIN 116
> > +#define ADC_MAX 922
> > +
> > +/* hi3660 Thermal Sensor Dev Structure */
> > +struct hi3660_thermal_sensor {
> > + struct hi3660_thermal_data *thermal;
> > + struct thermal_zone_device *tzd;
> > +
> > + uint32_t id;
> > +};
> > +
> > +struct hi3660_thermal_data {
> > + struct platform_device *pdev;
> > + struct hi3660_thermal_sensor sensors[HISI_MAX_SENSORS];
> > + void __iomem *thermal_base;
> > +};
> > +
> > +unsigned int sensor_reg_offset[HW_MAX_SENSORS] = { 0x1c, 0x5c, 0x9c,
> 0xdc };
> > +
> > +
> > +static int hi3660_thermal_get_temp(void *_sensor, int *temp)
> > +{
> > + struct hi3660_thermal_sensor *sensor = _sensor;
> > + struct hi3660_thermal_data *data = sensor->thermal;
> > + unsigned int idx;
> > + int val, average = 0, max = 0;
> > +
> > + if (sensor->id < HW_MAX_SENSORS) {
> > + val = readl(data->thermal_base + sensor_reg_offset[sensor-
> >id]);
> > + val = clamp_val(val, ADC_MIN, ADC_MAX);
> > + } else {
> > + for (idx = 0; idx < HW_MAX_SENSORS; idx++) {
> > + val = readl(data->thermal_base
> > + + sensor_reg_offset[idx]);
> > + val = clamp_val(val, ADC_MIN, ADC_MAX);
> > + average += val;
> > + if (val > max)
> > + max = val;
> > + }
> > +
> > + if (sensor->id == SENSOR_MAX)
> > + val = max;
> > + else if (sensor->id == SENSOR_AVG)
> > + val = average / HW_MAX_SENSORS;
> > + }
> > +
> > + *temp = ((val - ADC_MIN) * 165000) / (ADC_MAX - ADC_MIN) -
> 40000;
>
> Where do these constants come from (165000 and 40000) can these some
The sensor's temperature range is -40 to 125, that's the source of the constants.
> how
> be rearranged and described in DT (coefficients) and using the offset and
> slope fields?
That make sense, I will reconsider about it.
>
> > +
> > + return 0;
> > +}
> > +
> > +static struct thermal_zone_of_device_ops hi3660_of_thermal_ops = {
> > + .get_temp = hi3660_thermal_get_temp,
> > +};
> > +
> > +static int hi3660_thermal_register_sensor(struct platform_device *pdev,
> > + struct hi3660_thermal_data *data,
> > + struct hi3660_thermal_sensor *sensor,
> > + int index)
> > +{
> > + int ret = 0;
> > +
> > + sensor->id = index;
> > + sensor->thermal = data;
> > +
> > + sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev-
> >dev,
> > + sensor->id, sensor,
> &hi3660_of_thermal_ops);
> > + if (IS_ERR(sensor->tzd)) {
> > + ret = PTR_ERR(sensor->tzd);
> > + sensor->tzd = NULL;
> > + }
> > +
> > + return ret;
> > +}
> > +
> > +static void hi3660_thermal_toggle_sensor(struct hi3660_thermal_sensor
> *sensor,
> > + bool on)
> > +{
> > + struct thermal_zone_device *tzd = sensor->tzd;
> > +
> > + tzd->ops->set_mode(tzd,
> > + on ? THERMAL_DEVICE_ENABLED :
> THERMAL_DEVICE_DISABLED);
> > +}
> > +
> > +static int hi3660_thermal_probe(struct platform_device *pdev)
> > +{
> > + struct device *dev = &pdev->dev;
> > + struct hi3660_thermal_data *data;
> > + struct resource *res;
> > + int ret = 0;
> > + int i;
> > +
> > + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> > + if (!data)
> > + return -ENOMEM;
> > +
> > + data->pdev = pdev;
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + data->thermal_base = devm_ioremap_resource(dev, res);
> > + if (IS_ERR(data->thermal_base)) {
> > + dev_err(dev, "failed get reg base\n");
> > + return -ENOMEM;
> > + }
> > +
> > + platform_set_drvdata(pdev, data);
> > +
> > + for (i = 0; i < HISI_MAX_SENSORS; ++i) {
> > + ret = hi3660_thermal_register_sensor(pdev, data,
> > + &data->sensors[i], i);
> > + if (ret)
> > + dev_err(&pdev->dev,
> > + "failed to register thermal sensor%d: %d\n",
> > + i, ret);
>
> Do you really want to continue if some of the sensors fail to register?
Yes, because currently we only use one of these sensors, the others will register fail
>
> > + else
> > + hi3660_thermal_toggle_sensor(&data->sensors[i],
> true);
> > + }
> > +
> > + dev_info(&pdev->dev, "Thermal Sensor Loaded\n");
>
> Do you really need the above info in the kernel log?
That should be unnecessary, I will remove it.
>
> > + return 0;
> > +}
> > +
> > +static int hi3660_thermal_exit(struct platform_device *pdev)
> > +{
> > + struct hi3660_thermal_data *data = platform_get_drvdata(pdev);
> > + int i;
> > +
> > + for (i = 0; i < HISI_MAX_SENSORS; i++) {
> > + struct hi3660_thermal_sensor *sensor = &data->sensors[i];
> > +
> > + if (!sensor->tzd)
> > + continue;
>
> Why are you considering a valid case of not registering all expected
> sensors?
Because currently we only use one of these sensors.
> > +
> > + hi3660_thermal_toggle_sensor(sensor, false);
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static const struct of_device_id hi3660_thermal_id_table[] = {
> > + { .compatible = "hisilicon,hi3660-thermal" },
> > + {}
> > +};
> > +MODULE_DEVICE_TABLE(of, hi3660_thermal_id_table);
> > +
> > +static struct platform_driver hi3660_thermal_driver = {
> > + .probe = hi3660_thermal_probe,
> > + .remove = hi3660_thermal_exit,
> > + .driver = {
> > + .name = "hi3660_thermal",
> > + .of_match_table = hi3660_thermal_id_table,
> > + },
> > +};
> > +
> > +module_platform_driver(hi3660_thermal_driver);
> > +
> > +MODULE_AUTHOR("Tao Wang <[email protected]>");
> > +MODULE_AUTHOR("Leo Yan <[email protected]>");
> > +MODULE_DESCRIPTION("hi3660 thermal driver");
> > +MODULE_LICENSE("GPL v2");
> > --
> > 1.7.9.5
> >
From: Tao Wang <[email protected]>
This series adds thermal support for Hi3660 Soc, which support
all the hardware temperture sensors and two virtual sensors(one
for maximum value of all and one for average value of all).
Patch 1 add dt-binding document to describe how to config dt
for the driver.
Patch 2 introduces the thermal sensor driver.
Patch 3 add dts for the thermal senor driver on Hi3660.
hardware document can be found on
https://github.com/96boards/documentation/blob/master/ConsumerEdition/HiKey960/HardwareDocs/HiKey960_SoC_Reference_Manual.pdf
Changes in v2:
- correct alphabet order
- correct compatible name
- remove redundant property
- rebase changes on linux next
Changes in v3:
- remove unnecessary log print
- described all platform related parameters in DT
- make the driver forward compatible
Tao Wang (3):
dt-bindings: Document the hi3660 thermal sensor bindings
thermal: hisilicon: add thermal sensor driver for Hi3660
arm64: dts: register Hi3660's thermal sensor
.../devicetree/bindings/thermal/hisi-tsensor.txt | 23 +++
arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 10 +
drivers/thermal/Kconfig | 13 ++
drivers/thermal/Makefile | 1 +
drivers/thermal/hisi_tsensor.c | 223 +++++++++++++++++++++
include/dt-bindings/thermal/hi3660-thermal.h | 30 +++
6 files changed, 300 insertions(+)
create mode 100644 Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
create mode 100644 drivers/thermal/hisi_tsensor.c
create mode 100644 include/dt-bindings/thermal/hi3660-thermal.h
--
2.8.1
From: Tao Wang <[email protected]>
This adds documentation of device tree bindings for the
thermal sensor controller of hi3660 SoC.
Signed-off-by: Tao Wang <[email protected]>
---
.../devicetree/bindings/thermal/hisi-tsensor.txt | 23 ++++++++++++++++++++++
1 file changed, 23 insertions(+)
create mode 100644 Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
diff --git a/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt b/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
new file mode 100644
index 0000000..2ab0eb9
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
@@ -0,0 +1,23 @@
+* Temperature Sensor on hisilicon SoC
+
+** Required properties :
+
+- compatible: "hisilicon,thermal-tsensor".
+- reg: physical base address of thermal sensor and length of memory mapped
+ region.
+- offset: reg offset of each sensor.
+- coefficients: An array of integers (one signed cell) containing
+ coefficients to turn adc value to temperture.
+- hisi,adc-range: adc value range, minimum value is followed by maximum value.
+- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description.
+
+Example :
+
+tsensor: tsensor@FFF3000 {
+ compatible = "hisilicon,tsensor";
+ reg = <0x0 0xfff30000 0x0 0x1000>;
+ offset = <0x1c 0x5c 0x9c>;
+ coefficients = <165000 (-40000)>;
+ hisi,adc-range = <0x74 0x39A>;
+ #thermal-sensor-cells = <1>;
+};
--
2.8.1
From: Tao Wang <[email protected]>
Bind thermal sensor driver for Hi3660.
Signed-off-by: Tao Wang <[email protected]>
Signed-off-by: Leo Yan <[email protected]>
---
arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 10 ++++++++++
include/dt-bindings/thermal/hi3660-thermal.h | 30 ++++++++++++++++++++++++++++
2 files changed, 40 insertions(+)
create mode 100644 include/dt-bindings/thermal/hi3660-thermal.h
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index c6a1961..7e2081d 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -6,6 +6,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/hi3660-clock.h>
+#include <dt-bindings/thermal/hi3660-thermal.h>
/ {
compatible = "hisilicon,hi3660";
@@ -848,5 +849,14 @@
&sdio_cfg_func>;
status = "disabled";
};
+
+ tsensor: tsensor@FFF3000 {
+ compatible = "hisilicon,tsensor";
+ reg = <0x0 0xfff30000 0x0 0x1000>;
+ offset = <0x1c 0x5c 0x9c>;
+ coefficients = <165000 (-40000)>;
+ hisi,adc-range = <0x74 0x39A>;
+ #thermal-sensor-cells = <1>;
+ };
};
};
diff --git a/include/dt-bindings/thermal/hi3660-thermal.h b/include/dt-bindings/thermal/hi3660-thermal.h
new file mode 100644
index 0000000..1efe625
--- /dev/null
+++ b/include/dt-bindings/thermal/hi3660-thermal.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017 Hisilicon Limited.
+ * Copyright (c) 2017 Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DTS_HI3660_THERMAL_H
+#define __DTS_HI3660_THERMAL_H
+
+/* sensor id */
+#define LITTLE_CPU_TEMP 0
+#define BIG_CPU_TEMP 1
+#define GPU_TEMP 2
+#define MAX_TEMP 3
+#define AVG_TEMP 4
+
+#define THERMAL_NO_LIMIT (~0)
+
+#endif
--
2.8.1
From: Tao Wang <[email protected]>
This patch adds the support for thermal sensor of Hi3660 SoC.
this will register sensors for thermal framework and use device
tree to bind cooling device.
Signed-off-by: Tao Wang <[email protected]>
Signed-off-by: Leo Yan <[email protected]>
---
drivers/thermal/Kconfig | 13 +++
drivers/thermal/Makefile | 1 +
drivers/thermal/hisi_tsensor.c | 223 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 237 insertions(+)
create mode 100644 drivers/thermal/hisi_tsensor.c
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index b5b5fac..32f582d 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -203,6 +203,19 @@ config HISI_THERMAL
thermal framework. cpufreq is used as the cooling device to throttle
CPUs when the passive trip is crossed.
+config HISI_TSENSOR
+ tristate "Hisilicon tsensor driver"
+ depends on ARCH_HISI || COMPILE_TEST
+ depends on HAS_IOMEM
+ depends on OF
+ default y
+ help
+ Enable this to plug Hisilicon's tsensor driver into the Linux thermal
+ framework. Besides all the hardware sensors, this also support two
+ virtual sensors, one for maximum of all the hardware sensor, and
+ one for average of all the hardware sensor.
+ Compitable with Hi3660 or higher.
+
config IMX_THERMAL
tristate "Temperature sensor driver for Freescale i.MX SoCs"
depends on (ARCH_MXC && CPU_THERMAL) || COMPILE_TEST
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 094d703..8a16bd4 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_ST_THERMAL) += st/
obj-$(CONFIG_QCOM_TSENS) += qcom/
obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
+obj-$(CONFIG_HISI_TSENSOR) += hisi_tsensor.o
obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
diff --git a/drivers/thermal/hisi_tsensor.c b/drivers/thermal/hisi_tsensor.c
new file mode 100644
index 0000000..c8eec9d
--- /dev/null
+++ b/drivers/thermal/hisi_tsensor.c
@@ -0,0 +1,223 @@
+/*
+ * linux/drivers/thermal/hisi_tsensor.c
+ *
+ * Copyright (c) 2017 Hisilicon Limited.
+ * Copyright (c) 2017 Linaro Limited.
+ *
+ * Author: Tao Wang <[email protected]>
+ * Author: Leo Yan <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/thermal.h>
+
+#include "thermal_core.h"
+
+#define VIRTUAL_SENSORS 2
+
+/* hisi Thermal Sensor Dev Structure */
+struct hisi_thermal_sensor {
+ struct hisi_thermal_data *thermal;
+ struct thermal_zone_device *tzd;
+ unsigned int id;
+};
+
+struct hisi_thermal_data {
+ struct platform_device *pdev;
+ struct hisi_thermal_sensor *sensors;
+ void __iomem *thermal_base;
+ unsigned int *reg_offset;
+ unsigned int range[2];
+ unsigned int coef[2];
+ unsigned int max_hw_sensor;
+};
+
+static int hisi_thermal_get_temp(void *_sensor, int *temp)
+{
+ struct hisi_thermal_sensor *sensor = _sensor;
+ struct hisi_thermal_data *data = sensor->thermal;
+ unsigned int idx, adc_min, adc_max, max_sensor;
+ int val, average = 0, max = 0;
+
+ adc_min = data->range[0];
+ adc_max = data->range[1];
+ max_sensor = data->max_hw_sensor;
+
+ if (sensor->id < max_sensor) {
+ val = readl(data->thermal_base + data->reg_offset[sensor->id]);
+ val = clamp_val(val, adc_min, adc_max);
+ } else {
+ for (idx = 0; idx < max_sensor; idx++) {
+ val = readl(data->thermal_base
+ + data->reg_offset[idx]);
+ val = clamp_val(val, adc_min, adc_max);
+ average += val;
+ if (val > max)
+ max = val;
+ }
+
+ if (sensor->id == max_sensor)
+ val = max;
+ else
+ val = average / max_sensor;
+ }
+
+ *temp = ((val - adc_min) * data->coef[0]) / (adc_max - adc_min)
+ + data->coef[1];
+
+ return 0;
+}
+
+static struct thermal_zone_of_device_ops hisi_of_thermal_ops = {
+ .get_temp = hisi_thermal_get_temp,
+};
+
+static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor,
+ bool on)
+{
+ struct thermal_zone_device *tzd = sensor->tzd;
+
+ tzd->ops->set_mode(tzd,
+ on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);
+}
+
+static int hisi_thermal_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct hisi_thermal_data *data;
+ struct hisi_thermal_sensor *sensor;
+ struct resource *res;
+ unsigned int max_sensor;
+ int ret, i;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->pdev = pdev;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data->thermal_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(data->thermal_base)) {
+ dev_err(dev, "failed to get reg base\n");
+ return -ENOMEM;
+ }
+
+ max_sensor = of_property_count_u32_elems(np, "offset");
+ if (max_sensor < 0) {
+ dev_err(dev, "failed to get max sensor\n");
+ return -EINVAL;
+ }
+ data->max_hw_sensor = max_sensor;
+
+ data->sensors = devm_kzalloc(dev,
+ sizeof(*data->sensors) * (max_sensor + VIRTUAL_SENSORS),
+ GFP_KERNEL);
+ if (IS_ERR(data->sensors)) {
+ dev_err(dev, "failed to alloc sensors\n");
+ return -ENOMEM;
+ }
+
+ data->reg_offset = devm_kzalloc(dev,
+ sizeof(*data->reg_offset) * max_sensor, GFP_KERNEL);
+ if (IS_ERR(data->reg_offset)) {
+ dev_err(dev, "failed to alloc sensor offset\n");
+ return -ENOMEM;
+ }
+
+ ret = of_property_read_u32_array(np,
+ "offset", data->reg_offset, max_sensor);
+ if (ret < 0) {
+ dev_err(dev, "failed to get reg offset\n");
+ return -EINVAL;
+ }
+
+ ret = of_property_read_u32_array(np, "coefficients", data->coef, 2);
+ if (ret < 0) {
+ dev_err(dev, "failed to get coef\n");
+ return -EINVAL;
+ }
+
+ ret = of_property_read_u32_array(np, "hisi,adc-range", data->range, 2);
+ if (ret < 0) {
+ dev_err(dev, "failed to get range\n");
+ return -EINVAL;
+ }
+
+ platform_set_drvdata(pdev, data);
+
+ for (i = 0; i < max_sensor + VIRTUAL_SENSORS; ++i) {
+ sensor = &data->sensors[i];
+ sensor->id = i;
+ sensor->thermal = data;
+ sensor->tzd = thermal_zone_of_sensor_register(dev,
+ i, sensor, &hisi_of_thermal_ops);
+ if (IS_ERR(sensor->tzd)) {
+ sensor->tzd = NULL;
+ } else {
+ hisi_thermal_toggle_sensor(sensor, true);
+ dev_info(dev, "thermal sensor%d registered\n", i);
+ }
+ }
+
+ return 0;
+}
+
+static int hisi_thermal_exit(struct platform_device *pdev)
+{
+ struct hisi_thermal_data *data = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < data->max_hw_sensor + VIRTUAL_SENSORS; i++) {
+ struct hisi_thermal_sensor *sensor = &data->sensors[i];
+
+ if (!sensor->tzd)
+ continue;
+
+ hisi_thermal_toggle_sensor(sensor, false);
+ thermal_zone_of_sensor_unregister(&pdev->dev, sensor->tzd);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id hisi_thermal_id_table[] = {
+ { .compatible = "hisilicon,tsensor" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, hisi_thermal_id_table);
+
+static struct platform_driver hisi_thermal_driver = {
+ .probe = hisi_thermal_probe,
+ .remove = hisi_thermal_exit,
+ .driver = {
+ .name = "hisi_tsensor",
+ .of_match_table = hisi_thermal_id_table,
+ },
+};
+
+module_platform_driver(hisi_thermal_driver);
+
+MODULE_AUTHOR("Tao Wang <[email protected]>");
+MODULE_AUTHOR("Leo Yan <[email protected]>");
+MODULE_DESCRIPTION("hisi tsensor driver");
+MODULE_LICENSE("GPL v2");
--
2.8.1
On Thu, Aug 10, 2017 at 04:32:13PM +0800, Tao Wang wrote:
> From: Tao Wang <[email protected]>
>
> This adds documentation of device tree bindings for the
> thermal sensor controller of hi3660 SoC.
>
> Signed-off-by: Tao Wang <[email protected]>
> ---
> .../devicetree/bindings/thermal/hisi-tsensor.txt | 23 ++++++++++++++++++++++
> 1 file changed, 23 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
>
> diff --git a/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt b/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
> new file mode 100644
> index 0000000..2ab0eb9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
> @@ -0,0 +1,23 @@
> +* Temperature Sensor on hisilicon SoC
> +
> +** Required properties :
> +
> +- compatible: "hisilicon,thermal-tsensor".
Needs an SoC specific compatible.
> +- reg: physical base address of thermal sensor and length of memory mapped
> + region.
> +- offset: reg offset of each sensor.
Should be implied by the compatible.
> +- coefficients: An array of integers (one signed cell) containing
> + coefficients to turn adc value to temperture.
Needs a vendor prefix.
> +- hisi,adc-range: adc value range, minimum value is followed by maximum value.
> +- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description.
> +
> +Example :
> +
> +tsensor: tsensor@FFF3000 {
> + compatible = "hisilicon,tsensor";
> + reg = <0x0 0xfff30000 0x0 0x1000>;
> + offset = <0x1c 0x5c 0x9c>;
> + coefficients = <165000 (-40000)>;
> + hisi,adc-range = <0x74 0x39A>;
> + #thermal-sensor-cells = <1>;
> +};
> --
> 2.8.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
?? 2017/8/17 23:10, Rob Herring д??:
> On Thu, Aug 10, 2017 at 04:32:13PM +0800, Tao Wang wrote:
>> From: Tao Wang <[email protected]>
>>
>> This adds documentation of device tree bindings for the
>> thermal sensor controller of hi3660 SoC.
>>
>> Signed-off-by: Tao Wang <[email protected]>
>> ---
>> .../devicetree/bindings/thermal/hisi-tsensor.txt | 23 ++++++++++++++++++++++
>> 1 file changed, 23 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
>>
>> diff --git a/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt b/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
>> new file mode 100644
>> index 0000000..2ab0eb9
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
>> @@ -0,0 +1,23 @@
>> +* Temperature Sensor on hisilicon SoC
>> +
>> +** Required properties :
>> +
>> +- compatible: "hisilicon,thermal-tsensor".
>
> Needs an SoC specific compatible.
OK
>
>> +- reg: physical base address of thermal sensor and length of memory mapped
>> + region.
>> +- offset: reg offset of each sensor.
>
> Should be implied by the compatible.
Do you mean that the reg offset should not in dts?
>
>> +- coefficients: An array of integers (one signed cell) containing
>> + coefficients to turn adc value to temperture.
>
> Needs a vendor prefix.
OK
>
>> +- hisi,adc-range: adc value range, minimum value is followed by maximum value.
>> +- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description.
>> +
>> +Example :
>> +
>> +tsensor: tsensor@FFF3000 {
>> + compatible = "hisilicon,tsensor";
>> + reg = <0x0 0xfff30000 0x0 0x1000>;
>> + offset = <0x1c 0x5c 0x9c>;
>> + coefficients = <165000 (-40000)>;
>> + hisi,adc-range = <0x74 0x39A>;
>> + #thermal-sensor-cells = <1>;
>> +};
>> --
>> 2.8.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe devicetree" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
> .
>
From: Tao Wang <[email protected]>
This series adds thermal support for Hi3660 Soc, which support
all the hardware temperture sensors and two virtual sensors(one
for maximum value of all and one for average value of all).
Patch 1 add dt-binding document to describe how to config dt
for the driver.
Patch 2 introduces the thermal sensor driver.
Patch 3 add dts for the thermal senor driver on Hi3660.
Changes in v2:
- correct alphabet order
- correct compatible name
- remove redundant property
- rebase changes on linux next
Changes in v3:
- remove unnecessary log print
- described all platform related parameters in DT
- make the driver forward compatible
Changes in v4:
- add more description about the sensor in Documentation
- correct dts property name
Tao Wang (3):
dt-bindings: Document the hi3660 thermal sensor bindings
thermal: hisilicon: add thermal sensor driver for Hi3660
arm64: dts: register Hi3660's thermal sensor
.../devicetree/bindings/thermal/hisi-tsensor.txt | 37 ++++
arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 14 ++
drivers/thermal/Kconfig | 13 ++
drivers/thermal/Makefile | 1 +
drivers/thermal/hisi_tsensor.c | 209 +++++++++++++++++++++
include/dt-bindings/thermal/hi3660-thermal.h | 31 +++
6 files changed, 305 insertions(+)
create mode 100644 Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
create mode 100644 drivers/thermal/hisi_tsensor.c
create mode 100644 include/dt-bindings/thermal/hi3660-thermal.h
--
2.8.1
From: Tao Wang <[email protected]>
Bind thermal sensor driver for Hi3660.
Signed-off-by: Tao Wang <[email protected]>
Signed-off-by: Leo Yan <[email protected]>
---
arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 14 +++++++++++++
include/dt-bindings/thermal/hi3660-thermal.h | 31 ++++++++++++++++++++++++++++
2 files changed, 45 insertions(+)
create mode 100644 include/dt-bindings/thermal/hi3660-thermal.h
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index c6a1961..1ee6084 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -6,6 +6,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/hi3660-clock.h>
+#include <dt-bindings/thermal/hi3660-thermal.h>
/ {
compatible = "hisilicon,hi3660";
@@ -848,5 +849,18 @@
&sdio_cfg_func>;
status = "disabled";
};
+
+ tsensor: tsensor@fff30000 {
+ compatible = "hisilicon,hi3660-tsensor";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ reg = <0x0 0xfff3001c 0x0 0x4>,
+ <0x0 0xfff3005c 0x0 0x4>,
+ <0x0 0xfff3009c 0x0 0x4>;
+ hisi,tsensors = <HISI_MAX_TSENSORS>;
+ hisi,coef = <165000 (-40000)>;
+ hisi,adc-range = <0x74 0x39A>;
+ #thermal-sensor-cells = <1>;
+ };
};
};
diff --git a/include/dt-bindings/thermal/hi3660-thermal.h b/include/dt-bindings/thermal/hi3660-thermal.h
new file mode 100644
index 0000000..d9d9b6a
--- /dev/null
+++ b/include/dt-bindings/thermal/hi3660-thermal.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017 Hisilicon Limited.
+ * Copyright (c) 2017 Linaro Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DTS_HI3660_THERMAL_H
+#define __DTS_HI3660_THERMAL_H
+
+/* sensor id */
+#define LITTLE_CPU_TEMP 0
+#define BIG_CPU_TEMP 1
+#define GPU_TEMP 2
+#define MAX_TEMP 3
+#define AVG_TEMP 4
+
+#define HISI_MAX_TSENSORS 3
+#define THERMAL_NO_LIMIT (~0)
+
+#endif
--
2.8.1
From: Tao Wang <[email protected]>
This adds documentation of device tree bindings for the
thermal sensor controller of hi3660 SoC.
Signed-off-by: Tao Wang <[email protected]>
---
.../devicetree/bindings/thermal/hisi-tsensor.txt | 37 ++++++++++++++++++++++
1 file changed, 37 insertions(+)
create mode 100644 Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
diff --git a/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt b/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
new file mode 100644
index 0000000..4643dbe
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
@@ -0,0 +1,37 @@
+* Temperature Sensor on hisilicon SoC
+
+Hisilicon SoC supplies temperature sensor feature, each CPU cluster and G3D
+area contains a temperture sensor. The temperture sensor produces an output
+value which has a linear relationship with the temperture of the area.
+
+for Hi3660,
+sensor0 monitors the temperture of A53;
+sensor1 monitors the temperture of A72;
+sensor2 monitors the temperture of GPU;
+sensor3 is a virtual sensor, which produces the maximum value of all sensors;
+sensor4 is a virtual sensor, which produces the average value of all sensors.
+
+** Required properties :
+- compatible: "hisilicon,thermal-tsensor".
+- reg: physical reg address of thermal sensor and length of memory mapped
+ region.
+- hisi,tsensors: number of hardware tsensors
+- hisi,coef: An array of integers (one signed cell) containing
+ coefficients to turn adc value to temperture.
+- hisi,adc-range: adc value range, minimum value is followed by maximum value.
+- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description.
+
+Example :
+Hi3660:
+tsensor: tsensor@fff30000 {
+ compatible = "hisilicon,hi3660-tsensor";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ reg = <0x0 0xfff3001c 0x0 0x4>,
+ <0x0 0xfff3005c 0x0 0x4>,
+ <0x0 0xfff3009c 0x0 0x4>;
+ hisi,tsensors = <HISI_MAX_TSENSORS>;
+ hisi,coef = <165000 (-40000)>;
+ hisi,adc-range = <0x74 0x39A>;
+ #thermal-sensor-cells = <1>;
+};
--
2.8.1
From: Tao Wang <[email protected]>
This patch adds the support for thermal sensor of Hi3660 SoC.
this will register sensors for thermal framework and use device
tree to bind cooling device.
Signed-off-by: Tao Wang <[email protected]>
Signed-off-by: Leo Yan <[email protected]>
---
drivers/thermal/Kconfig | 13 +++
drivers/thermal/Makefile | 1 +
drivers/thermal/hisi_tsensor.c | 209 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 223 insertions(+)
create mode 100644 drivers/thermal/hisi_tsensor.c
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index b5b5fac..32f582d 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -203,6 +203,19 @@ config HISI_THERMAL
thermal framework. cpufreq is used as the cooling device to throttle
CPUs when the passive trip is crossed.
+config HISI_TSENSOR
+ tristate "Hisilicon tsensor driver"
+ depends on ARCH_HISI || COMPILE_TEST
+ depends on HAS_IOMEM
+ depends on OF
+ default y
+ help
+ Enable this to plug Hisilicon's tsensor driver into the Linux thermal
+ framework. Besides all the hardware sensors, this also support two
+ virtual sensors, one for maximum of all the hardware sensor, and
+ one for average of all the hardware sensor.
+ Compitable with Hi3660 or higher.
+
config IMX_THERMAL
tristate "Temperature sensor driver for Freescale i.MX SoCs"
depends on (ARCH_MXC && CPU_THERMAL) || COMPILE_TEST
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 094d703..8a16bd4 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_ST_THERMAL) += st/
obj-$(CONFIG_QCOM_TSENS) += qcom/
obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
+obj-$(CONFIG_HISI_TSENSOR) += hisi_tsensor.o
obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
diff --git a/drivers/thermal/hisi_tsensor.c b/drivers/thermal/hisi_tsensor.c
new file mode 100644
index 0000000..34cf2ba
--- /dev/null
+++ b/drivers/thermal/hisi_tsensor.c
@@ -0,0 +1,209 @@
+/*
+ * linux/drivers/thermal/hisi_tsensor.c
+ *
+ * Copyright (c) 2017 Hisilicon Limited.
+ * Copyright (c) 2017 Linaro Limited.
+ *
+ * Author: Tao Wang <[email protected]>
+ * Author: Leo Yan <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/thermal.h>
+
+#include "thermal_core.h"
+
+#define VIRTUAL_SENSORS 2
+
+/* hisi Thermal Sensor Dev Structure */
+struct hisi_thermal_sensor {
+ struct hisi_thermal_data *thermal;
+ struct thermal_zone_device *tzd;
+ void __iomem *sensor_reg;
+ unsigned int id;
+};
+
+struct hisi_thermal_data {
+ struct platform_device *pdev;
+ struct hisi_thermal_sensor *sensors;
+ unsigned int range[2];
+ unsigned int coef[2];
+ unsigned int max_hw_sensor;
+};
+
+static int hisi_thermal_get_temp(void *_sensor, int *temp)
+{
+ struct hisi_thermal_sensor *sensor = _sensor;
+ struct hisi_thermal_data *data = sensor->thermal;
+ unsigned int idx, adc_min, adc_max, max_sensor;
+ int val, average = 0, max = 0;
+
+ adc_min = data->range[0];
+ adc_max = data->range[1];
+ max_sensor = data->max_hw_sensor;
+
+ if (sensor->id < max_sensor) {
+ val = readl(sensor->sensor_reg);
+ val = clamp_val(val, adc_min, adc_max);
+ } else {
+ for (idx = 0; idx < max_sensor; idx++) {
+ val = readl(data->sensors[idx].sensor_reg);
+ val = clamp_val(val, adc_min, adc_max);
+ average += val;
+ if (val > max)
+ max = val;
+ }
+
+ if (sensor->id == max_sensor)
+ val = max;
+ else
+ val = average / max_sensor;
+ }
+
+ *temp = ((val - adc_min) * data->coef[0]) / (adc_max - adc_min)
+ + data->coef[1];
+
+ return 0;
+}
+
+static struct thermal_zone_of_device_ops hisi_of_thermal_ops = {
+ .get_temp = hisi_thermal_get_temp,
+};
+
+static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor,
+ bool on)
+{
+ struct thermal_zone_device *tzd = sensor->tzd;
+
+ tzd->ops->set_mode(tzd,
+ on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);
+}
+
+static int hisi_thermal_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct hisi_thermal_data *data;
+ struct hisi_thermal_sensor *sensor;
+ struct resource *res;
+ unsigned int max_sensor;
+ int ret, i;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->pdev = pdev;
+ ret = of_property_read_u32(np, "hisi,tsensors", &max_sensor);
+ if (ret < 0) {
+ dev_err(dev, "failed to get max sensor\n");
+ return -EINVAL;
+ }
+ data->max_hw_sensor = max_sensor;
+
+ data->sensors = devm_kzalloc(dev,
+ sizeof(*data->sensors) * (max_sensor + VIRTUAL_SENSORS),
+ GFP_KERNEL);
+ if (IS_ERR(data->sensors)) {
+ dev_err(dev, "failed to alloc sensors\n");
+ return -ENOMEM;
+ }
+
+ ret = of_property_read_u32_array(np, "hisi,coef", data->coef, 2);
+ if (ret < 0) {
+ dev_err(dev, "failed to get coef\n");
+ return -EINVAL;
+ }
+
+ ret = of_property_read_u32_array(np, "hisi,adc-range", data->range, 2);
+ if (ret < 0) {
+ dev_err(dev, "failed to get range\n");
+ return -EINVAL;
+ }
+
+ platform_set_drvdata(pdev, data);
+
+ for (i = 0; i < max_sensor + VIRTUAL_SENSORS; ++i) {
+ sensor = &data->sensors[i];
+ if (i < max_sensor) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ sensor->sensor_reg = devm_ioremap_resource(dev, res);
+ if (IS_ERR(sensor->sensor_reg)) {
+ dev_err(dev, "failed to get reg base\n");
+ return -ENOMEM;
+ }
+ }
+
+ sensor->id = i;
+ sensor->thermal = data;
+ sensor->tzd = thermal_zone_of_sensor_register(dev,
+ i, sensor, &hisi_of_thermal_ops);
+ if (IS_ERR(sensor->tzd)) {
+ sensor->tzd = NULL;
+ } else {
+ hisi_thermal_toggle_sensor(sensor, true);
+ dev_info(dev, "thermal sensor%d registered\n", i);
+ }
+ }
+
+ return 0;
+}
+
+static int hisi_thermal_exit(struct platform_device *pdev)
+{
+ struct hisi_thermal_data *data = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < data->max_hw_sensor + VIRTUAL_SENSORS; i++) {
+ struct hisi_thermal_sensor *sensor = &data->sensors[i];
+
+ if (!sensor->tzd)
+ continue;
+
+ hisi_thermal_toggle_sensor(sensor, false);
+ thermal_zone_of_sensor_unregister(&pdev->dev, sensor->tzd);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id hisi_thermal_id_table[] = {
+ { .compatible = "hisilicon,hi3660-tsensor" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, hisi_thermal_id_table);
+
+static struct platform_driver hisi_thermal_driver = {
+ .probe = hisi_thermal_probe,
+ .remove = hisi_thermal_exit,
+ .driver = {
+ .name = "hisi_tsensor",
+ .of_match_table = hisi_thermal_id_table,
+ },
+};
+
+module_platform_driver(hisi_thermal_driver);
+
+MODULE_AUTHOR("Tao Wang <[email protected]>");
+MODULE_AUTHOR("Leo Yan <[email protected]>");
+MODULE_DESCRIPTION("hisi tsensor driver");
+MODULE_LICENSE("GPL v2");
--
2.8.1
On 29/08/2017 10:17, Tao Wang wrote:
> From: Tao Wang <[email protected]>
>
> This adds documentation of device tree bindings for the
> thermal sensor controller of hi3660 SoC.
>
> Signed-off-by: Tao Wang <[email protected]>
> ---
> .../devicetree/bindings/thermal/hisi-tsensor.txt | 37 ++++++++++++++++++++++
> 1 file changed, 37 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
>
> diff --git a/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt b/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
> new file mode 100644
> index 0000000..4643dbe
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
> @@ -0,0 +1,37 @@
> +* Temperature Sensor on hisilicon SoC
> +
> +Hisilicon SoC supplies temperature sensor feature, each CPU cluster and G3D
> +area contains a temperture sensor. The temperture sensor produces an output
> +value which has a linear relationship with the temperture of the area.
> +
s/temperture/temperature/
> +for Hi3660,
> +sensor0 monitors the temperture of A53;
> +sensor1 monitors the temperture of A72;
> +sensor2 monitors the temperture of GPU;
> +sensor3 is a virtual sensor, which produces the maximum value of all sensors;
> +sensor4 is a virtual sensor, which produces the average value of all sensors.
I don't think we need to escribe the virtual sensors in the DT bindings.
> +** Required properties :
> +- compatible: "hisilicon,thermal-tsensor".
> +- reg: physical reg address of thermal sensor and length of memory mapped
> + region.
> +- hisi,tsensors: number of hardware tsensors
> +- hisi,coef: An array of integers (one signed cell) containing
> + coefficients to turn adc value to temperture.
> +- hisi,adc-range: adc value range, minimum value is followed by maximum value.
> +- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description.
> +
> +Example :
> +Hi3660:
> +tsensor: tsensor@fff30000 {
> + compatible = "hisilicon,hi3660-tsensor";
> + #address-cells = <2>;
> + #size-cells = <2>;
> + reg = <0x0 0xfff3001c 0x0 0x4>,
> + <0x0 0xfff3005c 0x0 0x4>,
> + <0x0 0xfff3009c 0x0 0x4>;
> + hisi,tsensors = <HISI_MAX_TSENSORS>;
> + hisi,coef = <165000 (-40000)>;
> + hisi,adc-range = <0x74 0x39A>;
Do we really need max sensors, coef and adc range to be specified in the DT?
Can't we assume the hi3660-tsensor has 3 sensors, and hard-code the
coef, adc, in the driver itself?
Can't this binding be merged with the hisilicon-thermal.txt?
Thanks.
-- Daniel
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
On 29/08/2017 10:17, Tao Wang wrote:
> From: Tao Wang <[email protected]>
>
> Bind thermal sensor driver for Hi3660.
The description is a bit light :)
> Signed-off-by: Tao Wang <[email protected]>
> Signed-off-by: Leo Yan <[email protected]>
> ---
> arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 14 +++++++++++++
> include/dt-bindings/thermal/hi3660-thermal.h | 31 ++++++++++++++++++++++++++++
> 2 files changed, 45 insertions(+)
> create mode 100644 include/dt-bindings/thermal/hi3660-thermal.h
>
> diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> index c6a1961..1ee6084 100644
> --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> @@ -6,6 +6,7 @@
>
> #include <dt-bindings/interrupt-controller/arm-gic.h>
> #include <dt-bindings/clock/hi3660-clock.h>
> +#include <dt-bindings/thermal/hi3660-thermal.h>
>
> / {
> compatible = "hisilicon,hi3660";
> @@ -848,5 +849,18 @@
> &sdio_cfg_func>;
> status = "disabled";
> };
> +
> + tsensor: tsensor@fff30000 {
> + compatible = "hisilicon,hi3660-tsensor";
> + #address-cells = <2>;
> + #size-cells = <2>;
> + reg = <0x0 0xfff3001c 0x0 0x4>,
> + <0x0 0xfff3005c 0x0 0x4>,
> + <0x0 0xfff3009c 0x0 0x4>;
> + hisi,tsensors = <HISI_MAX_TSENSORS>;
> + hisi,coef = <165000 (-40000)>;
> + hisi,adc-range = <0x74 0x39A>;
> + #thermal-sensor-cells = <1>;
> + };
> };
> };
> diff --git a/include/dt-bindings/thermal/hi3660-thermal.h b/include/dt-bindings/thermal/hi3660-thermal.h
> new file mode 100644
> index 0000000..d9d9b6a
> --- /dev/null
> +++ b/include/dt-bindings/thermal/hi3660-thermal.h
> @@ -0,0 +1,31 @@
> +/*
> + * Copyright (c) 2017 Hisilicon Limited.
> + * Copyright (c) 2017 Linaro Limited.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef __DTS_HI3660_THERMAL_H
> +#define __DTS_HI3660_THERMAL_H
> +
> +/* sensor id */
> +#define LITTLE_CPU_TEMP 0
> +#define BIG_CPU_TEMP 1
> +#define GPU_TEMP 2
Is it possible to stick to the sensor description?
eg.
#define HI3660_A53_TEMP 0
#define HI3660_A72_TEMP 1
#define HI3660_GPU_TEMP 2
> +#define MAX_TEMP 3
> +#define AVG_TEMP 4
It does not make sense to define AVG and MAX, they describe how is
computed the temperature. It makes more sense to define the group eg.
SOC_TEMP and add an attribute to the virtual sensor telling how you want
the temperature to be computed. That will make the code in the driver
much more simple, clear and clean.
> +#define HISI_MAX_TSENSORS 3> +#define THERMAL_NO_LIMIT (~0)
Already defined in dt-bindings/thermal.h
> +#endif
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
Hi Kevin,
On 29/08/2017 10:17, Tao Wang wrote:
> From: Tao Wang <[email protected]>
>
> This patch adds the support for thermal sensor of Hi3660 SoC.
for the Hi3660 SoC thermal sensor.
> this will register sensors for thermal framework and use device
> tree to bind cooling device.
Is it possible to give a pointer to some documentation or to describe
the hardware?
An explanation of the adc min max coef[] range[] conversion would be nice.
In addition, having the rational behind the average and the max would be
nice. Do we really need both avg and max as virtual sensor?
> Signed-off-by: Tao Wang <[email protected]>
> Signed-off-by: Leo Yan <[email protected]>
> ---
> drivers/thermal/Kconfig | 13 +++
> drivers/thermal/Makefile | 1 +
> drivers/thermal/hisi_tsensor.c | 209 +++++++++++++++++++++++++++++++++++++++++
IMO, we don't need a new file, but merge this code with the current
hisi_thermal.c driver. BTW, the hi6220 has also a tsensor which is
different from this one.
I suggest to base the hi3660 thermal driver on top of the cleanup I sent
for the hi6220.
> 3 files changed, 223 insertions(+)
> create mode 100644 drivers/thermal/hisi_tsensor.c
>
> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
> index b5b5fac..32f582d 100644
> --- a/drivers/thermal/Kconfig
> +++ b/drivers/thermal/Kconfig
> @@ -203,6 +203,19 @@ config HISI_THERMAL
> thermal framework. cpufreq is used as the cooling device to throttle
> CPUs when the passive trip is crossed.
>
> +config HISI_TSENSOR
> + tristate "Hisilicon tsensor driver"
> + depends on ARCH_HISI || COMPILE_TEST
> + depends on HAS_IOMEM
> + depends on OF
> + default y
> + help
> + Enable this to plug Hisilicon's tsensor driver into the Linux thermal
> + framework. Besides all the hardware sensors, this also support two
> + virtual sensors, one for maximum of all the hardware sensor, and
> + one for average of all the hardware sensor.
> + Compitable with Hi3660 or higher.
s/Compitable/Compatible/
> +
> config IMX_THERMAL
> tristate "Temperature sensor driver for Freescale i.MX SoCs"
> depends on (ARCH_MXC && CPU_THERMAL) || COMPILE_TEST
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 094d703..8a16bd4 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -56,6 +56,7 @@ obj-$(CONFIG_ST_THERMAL) += st/
> obj-$(CONFIG_QCOM_TSENS) += qcom/
> obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
> obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
> +obj-$(CONFIG_HISI_TSENSOR) += hisi_tsensor.o
> obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
> obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
> obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
> diff --git a/drivers/thermal/hisi_tsensor.c b/drivers/thermal/hisi_tsensor.c
> new file mode 100644
> index 0000000..34cf2ba
> --- /dev/null
> +++ b/drivers/thermal/hisi_tsensor.c
> @@ -0,0 +1,209 @@
> +/*
> + * linux/drivers/thermal/hisi_tsensor.c
> + *
> + * Copyright (c) 2017 Hisilicon Limited.
> + * Copyright (c) 2017 Linaro Limited.
> + *
> + * Author: Tao Wang <[email protected]>
> + * Author: Leo Yan <[email protected]>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/of.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/thermal.h>
> +
> +#include "thermal_core.h"
> +
> +#define VIRTUAL_SENSORS 2
> +
> +/* hisi Thermal Sensor Dev Structure */
> +struct hisi_thermal_sensor {
> + struct hisi_thermal_data *thermal;
> + struct thermal_zone_device *tzd;
> + void __iomem *sensor_reg;
> + unsigned int id;
> +};
> +
> +struct hisi_thermal_data {
> + struct platform_device *pdev;
> + struct hisi_thermal_sensor *sensors;
> + unsigned int range[2];
> + unsigned int coef[2];
> + unsigned int max_hw_sensor;
> +};
> +
> +static int hisi_thermal_get_temp(void *_sensor, int *temp)
> +{
> + struct hisi_thermal_sensor *sensor = _sensor;
> + struct hisi_thermal_data *data = sensor->thermal;
> + unsigned int idx, adc_min, adc_max, max_sensor;
> + int val, average = 0, max = 0;
> +
> + adc_min = data->range[0];
> + adc_max = data->range[1];
> + max_sensor = data->max_hw_sensor;
> +
> + if (sensor->id < max_sensor) {
> + val = readl(sensor->sensor_reg);
> + val = clamp_val(val, adc_min, adc_max);
That looks a bit fuzzy. Why not create a get_temp for physical sensor
and another one for the virtual? So there will be a clear distinction
between both.
> + } else {
> + for (idx = 0; idx < max_sensor; idx++) {
> + val = readl(data->sensors[idx].sensor_reg);
Below, it is assumed thermal_zone_of_sensor_register() can fail and
sensor->tzd becomes NULL. But no check is done here with the sensor's
tzd. Shall the code assume we take all the sensors even if a thermal
zone failed to register ?
> + val = clamp_val(val, adc_min, adc_max);
> + average += val;
> + if (val > max)
> + max = val;
> + }
> +
> + if (sensor->id == max_sensor)
> + val = max;
> + else
> + val = average / max_sensor;
> + }
>
> + *temp = ((val - adc_min) * data->coef[0]) / (adc_max - adc_min)
> + + data->coef[1];
Pre-compute (adc_max - adc_min) at init time and check it is greater
than zero, otherwise for a bad DT configuration we can end up with
division by zero and crash the kernel (assuming having adc ranges in the
DT is what we want).
> + return 0;
> +}
> +
> +static struct thermal_zone_of_device_ops hisi_of_thermal_ops = {
> + .get_temp = hisi_thermal_get_temp,
> +};
> +
> +static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor,
> + bool on)
> +{
> + struct thermal_zone_device *tzd = sensor->tzd;
> +
> + tzd->ops->set_mode(tzd,
> + on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);
> +}
> +
> +static int hisi_thermal_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + struct hisi_thermal_data *data;
> + struct hisi_thermal_sensor *sensor;
> + struct resource *res;
> + unsigned int max_sensor;
> + int ret, i;
> +
> + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> +
> + data->pdev = pdev;
> + ret = of_property_read_u32(np, "hisi,tsensors", &max_sensor);
> + if (ret < 0) {
> + dev_err(dev, "failed to get max sensor\n");
> + return -EINVAL;
> + }
> + data->max_hw_sensor = max_sensor;
Do we really need a max sensor definition in the DT? Isn't it something
we can deduce by looping with platform_get_resource below ?
eg.
while ((res = platform_get_resource(..., num_sensor++)) {
...
}
That said, I think we can assume there are 3 sensors always, no?
> + data->sensors = devm_kzalloc(dev,
> + sizeof(*data->sensors) * (max_sensor + VIRTUAL_SENSORS),
> + GFP_KERNEL);
> + if (IS_ERR(data->sensors)) {
s/IS_ERR(data->sensors)/!data->sensors/
> + dev_err(dev, "failed to alloc sensors\n");
No message on memory allocation failure, there is already one from the
mm framework.
> + return -ENOMEM;
> + }
> +
> + ret = of_property_read_u32_array(np, "hisi,coef", data->coef, 2);
> + if (ret < 0) {
> + dev_err(dev, "failed to get coef\n");
> + return -EINVAL;
return ret;
> + }
> +
> + ret = of_property_read_u32_array(np, "hisi,adc-range", data->range, 2);
> + if (ret < 0) {
> + dev_err(dev, "failed to get range\n");
> + return -EINVAL;
return ret;
> + }
Are these data really needed through DT? Isn't it something we can hardcode?
> + platform_set_drvdata(pdev, data);
> +
> + for (i = 0; i < max_sensor + VIRTUAL_SENSORS; ++i) {
> + sensor = &data->sensors[i];
> + if (i < max_sensor) {
> + res = platform_get_resource(pdev, IORESOURCE_MEM, i);
Error check?
> + sensor->sensor_reg = devm_ioremap_resource(dev, res);
> + if (IS_ERR(sensor->sensor_reg)) {
> + dev_err(dev, "failed to get reg base\n");
> + return -ENOMEM;
s/-ENOMEM/PTR_ERR(sensor->sensor_reg)/
> + }
> + }
> +
> + sensor->id = i;
How can we deal with holes in the DT?
> + sensor->thermal = data;
> + sensor->tzd = thermal_zone_of_sensor_register(dev,
> + i, sensor, &hisi_of_thermal_ops);
> + if (IS_ERR(sensor->tzd)) {
> + sensor->tzd = NULL;
> + } else {
> + hisi_thermal_toggle_sensor(sensor, true);
> + dev_info(dev, "thermal sensor%d registered\n", i);
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int hisi_thermal_exit(struct platform_device *pdev)
> +{
> + struct hisi_thermal_data *data = platform_get_drvdata(pdev);
> + int i;
> +
> + for (i = 0; i < data->max_hw_sensor + VIRTUAL_SENSORS; i++) {
> + struct hisi_thermal_sensor *sensor = &data->sensors[i];
> +
> + if (!sensor->tzd)
> + continue;
> +
> + hisi_thermal_toggle_sensor(sensor, false);
> + thermal_zone_of_sensor_unregister(&pdev->dev, sensor->tzd);
> + }
> +
> + return 0;
> +}
> +
> +static const struct of_device_id hisi_thermal_id_table[] = {
> + { .compatible = "hisilicon,hi3660-tsensor" },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, hisi_thermal_id_table);
> +
> +static struct platform_driver hisi_thermal_driver = {
> + .probe = hisi_thermal_probe,
> + .remove = hisi_thermal_exit,
> + .driver = {
> + .name = "hisi_tsensor",
> + .of_match_table = hisi_thermal_id_table,
> + },
> +};
> +
> +module_platform_driver(hisi_thermal_driver);
> +
> +MODULE_AUTHOR("Tao Wang <[email protected]>");
> +MODULE_AUTHOR("Leo Yan <[email protected]>");
> +MODULE_DESCRIPTION("hisi tsensor driver");
> +MODULE_LICENSE("GPL v2");
>
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
在 2017/9/1 2:24, Daniel Lezcano 写道:
> On 29/08/2017 10:17, Tao Wang wrote:
>> From: Tao Wang <[email protected]>
>>
>> This adds documentation of device tree bindings for the
>> thermal sensor controller of hi3660 SoC.
>>
>> Signed-off-by: Tao Wang <[email protected]>
>> ---
>> .../devicetree/bindings/thermal/hisi-tsensor.txt | 37 ++++++++++++++++++++++
>> 1 file changed, 37 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
>>
>> diff --git a/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt b/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
>> new file mode 100644
>> index 0000000..4643dbe
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
>> @@ -0,0 +1,37 @@
>> +* Temperature Sensor on hisilicon SoC
>> +
>> +Hisilicon SoC supplies temperature sensor feature, each CPU cluster and G3D
>> +area contains a temperture sensor. The temperture sensor produces an output
>> +value which has a linear relationship with the temperture of the area.
>> +
>
> s/temperture/temperature/
THX
>
>> +for Hi3660,
>> +sensor0 monitors the temperture of A53;
>> +sensor1 monitors the temperture of A72;
>> +sensor2 monitors the temperture of GPU;
>> +sensor3 is a virtual sensor, which produces the maximum value of all sensors;
>> +sensor4 is a virtual sensor, which produces the average value of all sensors.
>
> I don't think we need to escribe the virtual sensors in the DT bindings.
I just want to let user know the sensor id of virtual sensor, I also define it in header file, so the header file is enough?
>
>> +** Required properties :
>> +- compatible: "hisilicon,thermal-tsensor".
>> +- reg: physical reg address of thermal sensor and length of memory mapped
>> + region.
>> +- hisi,tsensors: number of hardware tsensors
>> +- hisi,coef: An array of integers (one signed cell) containing
>> + coefficients to turn adc value to temperture.
>> +- hisi,adc-range: adc value range, minimum value is followed by maximum value.
>> +- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a description.
>> +
>> +Example :
>> +Hi3660:
>> +tsensor: tsensor@fff30000 {
>> + compatible = "hisilicon,hi3660-tsensor";
>> + #address-cells = <2>;
>> + #size-cells = <2>;
>> + reg = <0x0 0xfff3001c 0x0 0x4>,
>> + <0x0 0xfff3005c 0x0 0x4>,
>> + <0x0 0xfff3009c 0x0 0x4>;
>> + hisi,tsensors = <HISI_MAX_TSENSORS>;
>> + hisi,coef = <165000 (-40000)>;
>> + hisi,adc-range = <0x74 0x39A>;
>
> Do we really need max sensors, coef and adc range to be specified in the DT?
>
> Can't we assume the hi3660-tsensor has 3 sensors, and hard-code the
> coef, adc, in the driver itself?
My purpose is to make the driver be compitable with our future platform.
>
> Can't this binding be merged with the hisilicon-thermal.txt?
>
> Thanks.
>
> -- Daniel
>
>
在 2017/9/1 5:17, Daniel Lezcano 写道:
>
> Hi Kevin,
>
>
> On 29/08/2017 10:17, Tao Wang wrote:
>> From: Tao Wang <[email protected]>
>>
>> This patch adds the support for thermal sensor of Hi3660 SoC.
>
> for the Hi3660 SoC thermal sensor.
>
>> this will register sensors for thermal framework and use device
>> tree to bind cooling device.
>
> Is it possible to give a pointer to some documentation or to describe
> the hardware?
Yes, there used to be on patch V3, I removed it on V4.
>
> An explanation of the adc min max coef[] range[] conversion would be nice.
OK
>
> In addition, having the rational behind the average and the max would be
> nice. Do we really need both avg and max as virtual sensor?
We only need max currently.
>
>> Signed-off-by: Tao Wang <[email protected]>
>> Signed-off-by: Leo Yan <[email protected]>
>> ---
>> drivers/thermal/Kconfig | 13 +++
>> drivers/thermal/Makefile | 1 +
>> drivers/thermal/hisi_tsensor.c | 209 +++++++++++++++++++++++++++++++++++++++++
>
>
> IMO, we don't need a new file, but merge this code with the current
> hisi_thermal.c driver. BTW, the hi6220 has also a tsensor which is
> different from this one.
>
> I suggest to base the hi3660 thermal driver on top of the cleanup I sent
> for the hi6220.
The tsensor of hi3660 is a different one, merging the code with hi6220 will need a lot of change.
>
>> 3 files changed, 223 insertions(+)
>> create mode 100644 drivers/thermal/hisi_tsensor.c
>>
>> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
>> index b5b5fac..32f582d 100644
>> --- a/drivers/thermal/Kconfig
>> +++ b/drivers/thermal/Kconfig
>> @@ -203,6 +203,19 @@ config HISI_THERMAL
>> thermal framework. cpufreq is used as the cooling device to throttle
>> CPUs when the passive trip is crossed.
>>
>> +config HISI_TSENSOR
>> + tristate "Hisilicon tsensor driver"
>> + depends on ARCH_HISI || COMPILE_TEST
>> + depends on HAS_IOMEM
>> + depends on OF
>> + default y
>> + help
>> + Enable this to plug Hisilicon's tsensor driver into the Linux thermal
>> + framework. Besides all the hardware sensors, this also support two
>> + virtual sensors, one for maximum of all the hardware sensor, and
>> + one for average of all the hardware sensor.
>> + Compitable with Hi3660 or higher.
>
> s/Compitable/Compatible/
OK
>
>> +
>> config IMX_THERMAL
>> tristate "Temperature sensor driver for Freescale i.MX SoCs"
>> depends on (ARCH_MXC && CPU_THERMAL) || COMPILE_TEST
>> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
>> index 094d703..8a16bd4 100644
>> --- a/drivers/thermal/Makefile
>> +++ b/drivers/thermal/Makefile
>> @@ -56,6 +56,7 @@ obj-$(CONFIG_ST_THERMAL) += st/
>> obj-$(CONFIG_QCOM_TSENS) += qcom/
>> obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
>> obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
>> +obj-$(CONFIG_HISI_TSENSOR) += hisi_tsensor.o
>> obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
>> obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
>> obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
>> diff --git a/drivers/thermal/hisi_tsensor.c b/drivers/thermal/hisi_tsensor.c
>> new file mode 100644
>> index 0000000..34cf2ba
>> --- /dev/null
>> +++ b/drivers/thermal/hisi_tsensor.c
>> @@ -0,0 +1,209 @@
>> +/*
>> + * linux/drivers/thermal/hisi_tsensor.c
>> + *
>> + * Copyright (c) 2017 Hisilicon Limited.
>> + * Copyright (c) 2017 Linaro Limited.
>> + *
>> + * Author: Tao Wang <[email protected]>
>> + * Author: Leo Yan <[email protected]>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; version 2 of the License.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/device.h>
>> +#include <linux/err.h>
>> +#include <linux/io.h>
>> +#include <linux/kernel.h>
>> +#include <linux/of.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/thermal.h>
>> +
>> +#include "thermal_core.h"
>> +
>> +#define VIRTUAL_SENSORS 2
>> +
>> +/* hisi Thermal Sensor Dev Structure */
>> +struct hisi_thermal_sensor {
>> + struct hisi_thermal_data *thermal;
>> + struct thermal_zone_device *tzd;
>> + void __iomem *sensor_reg;
>> + unsigned int id;
>> +};
>> +
>> +struct hisi_thermal_data {
>> + struct platform_device *pdev;
>> + struct hisi_thermal_sensor *sensors;
>> + unsigned int range[2];
>> + unsigned int coef[2];
>> + unsigned int max_hw_sensor;
>> +};
>> +
>> +static int hisi_thermal_get_temp(void *_sensor, int *temp)
>> +{
>> + struct hisi_thermal_sensor *sensor = _sensor;
>> + struct hisi_thermal_data *data = sensor->thermal;
>> + unsigned int idx, adc_min, adc_max, max_sensor;
>> + int val, average = 0, max = 0;
>> +
>> + adc_min = data->range[0];
>> + adc_max = data->range[1];
>> + max_sensor = data->max_hw_sensor;
>> +
>> + if (sensor->id < max_sensor) {
>> + val = readl(sensor->sensor_reg);
>> + val = clamp_val(val, adc_min, adc_max);
>
> That looks a bit fuzzy. Why not create a get_temp for physical sensor
> and another one for the virtual? So there will be a clear distinction
> between both.
make sense
>
>> + } else {
>> + for (idx = 0; idx < max_sensor; idx++) {
>> + val = readl(data->sensors[idx].sensor_reg);
>
> Below, it is assumed thermal_zone_of_sensor_register() can fail and
> sensor->tzd becomes NULL. But no check is done here with the sensor's
> tzd. Shall the code assume we take all the sensors even if a thermal
> zone failed to register ?
Yes, thermal zone failed to register didn't impact the code here. If the tzone only bind to the max SoC temperature, all the physical sensor will failed to register tzone.
>
>> + val = clamp_val(val, adc_min, adc_max);
>> + average += val;
>> + if (val > max)
>> + max = val;
>> + }
>> +
>> + if (sensor->id == max_sensor)
>> + val = max;
>> + else
>> + val = average / max_sensor;
>> + }
>>
>> + *temp = ((val - adc_min) * data->coef[0]) / (adc_max - adc_min)
>> + + data->coef[1];
>
> Pre-compute (adc_max - adc_min) at init time and check it is greater
> than zero, otherwise for a bad DT configuration we can end up with
> division by zero and crash the kernel (assuming having adc ranges in the
> DT is what we want).
OK
>
>> + return 0;
>> +}
>> +
>> +static struct thermal_zone_of_device_ops hisi_of_thermal_ops = {
>> + .get_temp = hisi_thermal_get_temp,
>> +};
>> +
>> +static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor,
>> + bool on)
>> +{
>> + struct thermal_zone_device *tzd = sensor->tzd;
>> +
>> + tzd->ops->set_mode(tzd,
>> + on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);
>> +}
>> +
>> +static int hisi_thermal_probe(struct platform_device *pdev)
>> +{
>> + struct device *dev = &pdev->dev;
>> + struct device_node *np = dev->of_node;
>> + struct hisi_thermal_data *data;
>> + struct hisi_thermal_sensor *sensor;
>> + struct resource *res;
>> + unsigned int max_sensor;
>> + int ret, i;
>> +
>> + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
>> + if (!data)
>> + return -ENOMEM;
>> +
>> + data->pdev = pdev;
>> + ret = of_property_read_u32(np, "hisi,tsensors", &max_sensor);
>> + if (ret < 0) {
>> + dev_err(dev, "failed to get max sensor\n");
>> + return -EINVAL;
>> + }
>> + data->max_hw_sensor = max_sensor;
>
> Do we really need a max sensor definition in the DT? Isn't it something
> we can deduce by looping with platform_get_resource below ?
>
> eg.
>
> while ((res = platform_get_resource(..., num_sensor++)) {
> ...
> }
>
> That said, I think we can assume there are 3 sensors always, no?
If we have three CPU cluster or two cluster share the same sensor in future, that number is certain on hi3660
>
>> + data->sensors = devm_kzalloc(dev,
>> + sizeof(*data->sensors) * (max_sensor + VIRTUAL_SENSORS),
>> + GFP_KERNEL);
>> + if (IS_ERR(data->sensors)) {
>
> s/IS_ERR(data->sensors)/!data->sensors/
>
>> + dev_err(dev, "failed to alloc sensors\n");
>
> No message on memory allocation failure, there is already one from the
> mm framework.
OK
>
>> + return -ENOMEM;
>> + }
>> +
>> + ret = of_property_read_u32_array(np, "hisi,coef", data->coef, 2);
>> + if (ret < 0) {
>> + dev_err(dev, "failed to get coef\n");
>> + return -EINVAL;
>
> return ret;
>
>> + }
>> +
>> + ret = of_property_read_u32_array(np, "hisi,adc-range", data->range, 2);
>> + if (ret < 0) {
>> + dev_err(dev, "failed to get range\n");
>> + return -EINVAL;
>
> return ret;
OK
>
>> + }
>
> Are these data really needed through DT? Isn't it something we can hardcode?
>
>> + platform_set_drvdata(pdev, data);
>> +
>> + for (i = 0; i < max_sensor + VIRTUAL_SENSORS; ++i) {
>> + sensor = &data->sensors[i];
>> + if (i < max_sensor) {
>> + res = platform_get_resource(pdev, IORESOURCE_MEM, i);
>
> Error check?
devm_ioremap_resource will handle it
>
>> + sensor->sensor_reg = devm_ioremap_resource(dev, res);
>> + if (IS_ERR(sensor->sensor_reg)) {
>> + dev_err(dev, "failed to get reg base\n");
>> + return -ENOMEM;
>
> s/-ENOMEM/PTR_ERR(sensor->sensor_reg)/
OK
>
>> + }
>> + }
>> +
>> + sensor->id = i;
>
> How can we deal with holes in the DT?Do you mean the holes of sensor id?
>
>> + sensor->thermal = data;
>> + sensor->tzd = thermal_zone_of_sensor_register(dev,
>> + i, sensor, &hisi_of_thermal_ops);
>> + if (IS_ERR(sensor->tzd)) {
>> + sensor->tzd = NULL;
>> + } else {
>> + hisi_thermal_toggle_sensor(sensor, true);
>> + dev_info(dev, "thermal sensor%d registered\n", i);
>> + }
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int hisi_thermal_exit(struct platform_device *pdev)
>> +{
>> + struct hisi_thermal_data *data = platform_get_drvdata(pdev);
>> + int i;
>> +
>> + for (i = 0; i < data->max_hw_sensor + VIRTUAL_SENSORS; i++) {
>> + struct hisi_thermal_sensor *sensor = &data->sensors[i];
>> +
>> + if (!sensor->tzd)
>> + continue;
>> +
>> + hisi_thermal_toggle_sensor(sensor, false);
>> + thermal_zone_of_sensor_unregister(&pdev->dev, sensor->tzd);
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static const struct of_device_id hisi_thermal_id_table[] = {
>> + { .compatible = "hisilicon,hi3660-tsensor" },
>> + {}
>> +};
>> +MODULE_DEVICE_TABLE(of, hisi_thermal_id_table);
>> +
>> +static struct platform_driver hisi_thermal_driver = {
>> + .probe = hisi_thermal_probe,
>> + .remove = hisi_thermal_exit,
>> + .driver = {
>> + .name = "hisi_tsensor",
>> + .of_match_table = hisi_thermal_id_table,
>> + },
>> +};
>> +
>> +module_platform_driver(hisi_thermal_driver);
>> +
>> +MODULE_AUTHOR("Tao Wang <[email protected]>");
>> +MODULE_AUTHOR("Leo Yan <[email protected]>");
>> +MODULE_DESCRIPTION("hisi tsensor driver");
>> +MODULE_LICENSE("GPL v2");
>>
>
>
在 2017/9/1 5:13, Daniel Lezcano 写道:
> On 29/08/2017 10:17, Tao Wang wrote:
>> From: Tao Wang <[email protected]>
>>
>> Bind thermal sensor driver for Hi3660.
>
> The description is a bit light :)
All right
>
>
>> Signed-off-by: Tao Wang <[email protected]>
>> Signed-off-by: Leo Yan <[email protected]>
>> ---
>> arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 14 +++++++++++++
>> include/dt-bindings/thermal/hi3660-thermal.h | 31 ++++++++++++++++++++++++++++
>> 2 files changed, 45 insertions(+)
>> create mode 100644 include/dt-bindings/thermal/hi3660-thermal.h
>>
>> diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
>> index c6a1961..1ee6084 100644
>> --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
>> +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
>> @@ -6,6 +6,7 @@
>>
>> #include <dt-bindings/interrupt-controller/arm-gic.h>
>> #include <dt-bindings/clock/hi3660-clock.h>
>> +#include <dt-bindings/thermal/hi3660-thermal.h>
>>
>> / {
>> compatible = "hisilicon,hi3660";
>> @@ -848,5 +849,18 @@
>> &sdio_cfg_func>;
>> status = "disabled";
>> };
>> +
>> + tsensor: tsensor@fff30000 {
>> + compatible = "hisilicon,hi3660-tsensor";
>> + #address-cells = <2>;
>> + #size-cells = <2>;
>> + reg = <0x0 0xfff3001c 0x0 0x4>,
>> + <0x0 0xfff3005c 0x0 0x4>,
>> + <0x0 0xfff3009c 0x0 0x4>;
>> + hisi,tsensors = <HISI_MAX_TSENSORS>;
>> + hisi,coef = <165000 (-40000)>;
>> + hisi,adc-range = <0x74 0x39A>;
>> + #thermal-sensor-cells = <1>;
>> + };
>> };
>> };
>> diff --git a/include/dt-bindings/thermal/hi3660-thermal.h b/include/dt-bindings/thermal/hi3660-thermal.h
>> new file mode 100644
>> index 0000000..d9d9b6a
>> --- /dev/null
>> +++ b/include/dt-bindings/thermal/hi3660-thermal.h
>> @@ -0,0 +1,31 @@
>> +/*
>> + * Copyright (c) 2017 Hisilicon Limited.
>> + * Copyright (c) 2017 Linaro Limited.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; version 2 of the License.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef __DTS_HI3660_THERMAL_H
>> +#define __DTS_HI3660_THERMAL_H
>> +
>> +/* sensor id */
>> +#define LITTLE_CPU_TEMP 0
>> +#define BIG_CPU_TEMP 1
>> +#define GPU_TEMP 2
>
> Is it possible to stick to the sensor description?
OK
>
> eg.
>
> #define HI3660_A53_TEMP 0
> #define HI3660_A72_TEMP 1
> #define HI3660_GPU_TEMP 2
>
>> +#define MAX_TEMP 3
>> +#define AVG_TEMP 4
>
> It does not make sense to define AVG and MAX, they describe how is
> computed the temperature. It makes more sense to define the group eg.
> SOC_TEMP and add an attribute to the virtual sensor telling how you want
> the temperature to be computed. That will make the code in the driver
> much more simple, clear and clean.
You inspired me, actually the thermal zone just want the SoC temp, my driver only need to offer one virtual sensor, we don't need the sensor id any more
>
>> +#define HISI_MAX_TSENSORS 3> +#define THERMAL_NO_LIMIT (~0)
>
> Already defined in dt-bindings/thermal.h
>
>> +#endif
>
>
>
On 04/09/2017 08:39, Wangtao (Kevin, Kirin) wrote:
>
>
> 在 2017/9/1 2:24, Daniel Lezcano 写道:
>> On 29/08/2017 10:17, Tao Wang wrote:
>>> From: Tao Wang <[email protected]>
>>>
>>> This adds documentation of device tree bindings for the
>>> thermal sensor controller of hi3660 SoC.
>>>
>>> Signed-off-by: Tao Wang <[email protected]>
>>> ---
>>> .../devicetree/bindings/thermal/hisi-tsensor.txt | 37
>>> ++++++++++++++++++++++
>>> 1 file changed, 37 insertions(+)
>>> create mode 100644
>>> Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
>>>
>>> diff --git
>>> a/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
>>> b/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
>>> new file mode 100644
>>> index 0000000..4643dbe
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/thermal/hisi-tsensor.txt
>>> @@ -0,0 +1,37 @@
>>> +* Temperature Sensor on hisilicon SoC
>>> +
>>> +Hisilicon SoC supplies temperature sensor feature, each CPU cluster
>>> and G3D
>>> +area contains a temperture sensor. The temperture sensor produces an
>>> output
>>> +value which has a linear relationship with the temperture of the area.
>>> +
>>
>> s/temperture/temperature/
> THX
>>
>>> +for Hi3660,
>>> +sensor0 monitors the temperture of A53;
>>> +sensor1 monitors the temperture of A72;
>>> +sensor2 monitors the temperture of GPU;
>>> +sensor3 is a virtual sensor, which produces the maximum value of all
>>> sensors;
>>> +sensor4 is a virtual sensor, which produces the average value of all
>>> sensors.
>>
>> I don't think we need to escribe the virtual sensors in the DT bindings.
> I just want to let user know the sensor id of virtual sensor, I also
> define it in header file, so the header file is enough?
The virtual sensor (or something else) should be a separate, generic
thing to be used for anyone.
>>> +** Required properties :
>>> +- compatible: "hisilicon,thermal-tsensor".
>>> +- reg: physical reg address of thermal sensor and length of memory
>>> mapped
>>> + region.
>>> +- hisi,tsensors: number of hardware tsensors
>>> +- hisi,coef: An array of integers (one signed cell) containing
>>> + coefficients to turn adc value to temperture.
>>> +- hisi,adc-range: adc value range, minimum value is followed by
>>> maximum value.
>>> +- #thermal-sensor-cells: Should be 1. See ./thermal.txt for a
>>> description.
>>> +
>>> +Example :
>>> +Hi3660:
>>> +tsensor: tsensor@fff30000 {
>>> + compatible = "hisilicon,hi3660-tsensor";
>>> + #address-cells = <2>;
>>> + #size-cells = <2>;
>>> + reg = <0x0 0xfff3001c 0x0 0x4>,
>>> + <0x0 0xfff3005c 0x0 0x4>,
>>> + <0x0 0xfff3009c 0x0 0x4>;
>>> + hisi,tsensors = <HISI_MAX_TSENSORS>;
>>> + hisi,coef = <165000 (-40000)>;
>>> + hisi,adc-range = <0x74 0x39A>;
>>
>> Do we really need max sensors, coef and adc range to be specified in
>> the DT?
>>
>> Can't we assume the hi3660-tsensor has 3 sensors, and hard-code the
>> coef, adc, in the driver itself?
> My purpose is to make the driver be compitable with our future platform.
I don't see the point. The compatibility could be handled in the driver
itself, no?
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
Hi Kevin,
On 04/09/2017 09:56, Wangtao (Kevin, Kirin) wrote:
>
>
> 在 2017/9/1 5:17, Daniel Lezcano 写道:
>>
>> Hi Kevin,
>>
>>
>> On 29/08/2017 10:17, Tao Wang wrote:
>>> From: Tao Wang <[email protected]>
>>>
>>> This patch adds the support for thermal sensor of Hi3660 SoC.
>>
>> for the Hi3660 SoC thermal sensor.
>>
>>> this will register sensors for thermal framework and use device
>>> tree to bind cooling device.
>>
>> Is it possible to give a pointer to some documentation or to describe
>> the hardware?
> Yes, there used to be on patch V3, I removed it on V4.
>>
>> An explanation of the adc min max coef[] range[] conversion would be
>> nice.
> OK
>>
>> In addition, having the rational behind the average and the max would be
>> nice. Do we really need both avg and max as virtual sensor?
> We only need max currently.
>>
>>> Signed-off-by: Tao Wang <[email protected]>
>>> Signed-off-by: Leo Yan <[email protected]>
>>> ---
>>> drivers/thermal/Kconfig | 13 +++
>>> drivers/thermal/Makefile | 1 +
>>> drivers/thermal/hisi_tsensor.c | 209
>>> +++++++++++++++++++++++++++++++++++++++++
>>
>>
>> IMO, we don't need a new file, but merge this code with the current
>> hisi_thermal.c driver. BTW, the hi6220 has also a tsensor which is
>> different from this one.
>>
>> I suggest to base the hi3660 thermal driver on top of the cleanup I sent
>> for the hi6220.
> The tsensor of hi3660 is a different one, merging the code with hi6220
> will need a lot of change.
Have a look at the hisi_thermal.c at:
https://git.linaro.org/people/daniel.lezcano/linux.git/tree/drivers/thermal/hisi_thermal.c?h=thermal/hikey-4.14
after the cleanup I recently sent.
I'm pretty sure, with a little effort, we can merge both.
Especially if the virtual things is separated.
At the end, what do we do ? Read a register.
>>> 3 files changed, 223 insertions(+)
>>> create mode 100644 drivers/thermal/hisi_tsensor.c
>>>
>>> diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
>>> index b5b5fac..32f582d 100644
>>> --- a/drivers/thermal/Kconfig
>>> +++ b/drivers/thermal/Kconfig
>>> @@ -203,6 +203,19 @@ config HISI_THERMAL
>>> thermal framework. cpufreq is used as the cooling device to
>>> throttle
>>> CPUs when the passive trip is crossed.
>>> +config HISI_TSENSOR
>>> + tristate "Hisilicon tsensor driver"
>>> + depends on ARCH_HISI || COMPILE_TEST
>>> + depends on HAS_IOMEM
>>> + depends on OF
>>> + default y
>>> + help
>>> + Enable this to plug Hisilicon's tsensor driver into the Linux
>>> thermal
>>> + framework. Besides all the hardware sensors, this also support
>>> two
>>> + virtual sensors, one for maximum of all the hardware sensor, and
>>> + one for average of all the hardware sensor.
>>> + Compitable with Hi3660 or higher.
>>
>> s/Compitable/Compatible/
> OK
>>
>>> +
>>> config IMX_THERMAL
>>> tristate "Temperature sensor driver for Freescale i.MX SoCs"
>>> depends on (ARCH_MXC && CPU_THERMAL) || COMPILE_TEST
>>> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
>>> index 094d703..8a16bd4 100644
>>> --- a/drivers/thermal/Makefile
>>> +++ b/drivers/thermal/Makefile
>>> @@ -56,6 +56,7 @@ obj-$(CONFIG_ST_THERMAL) += st/
>>> obj-$(CONFIG_QCOM_TSENS) += qcom/
>>> obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
>>> obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
>>> +obj-$(CONFIG_HISI_TSENSOR) += hisi_tsensor.o
>>> obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
>>> obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
>>> obj-$(CONFIG_ZX2967_THERMAL) += zx2967_thermal.o
>>> diff --git a/drivers/thermal/hisi_tsensor.c
>>> b/drivers/thermal/hisi_tsensor.c
>>> new file mode 100644
>>> index 0000000..34cf2ba
>>> --- /dev/null
>>> +++ b/drivers/thermal/hisi_tsensor.c
>>> @@ -0,0 +1,209 @@
>>> +/*
>>> + * linux/drivers/thermal/hisi_tsensor.c
>>> + *
>>> + * Copyright (c) 2017 Hisilicon Limited.
>>> + * Copyright (c) 2017 Linaro Limited.
>>> + *
>>> + * Author: Tao Wang <[email protected]>
>>> + * Author: Leo Yan <[email protected]>
>>> + *
>>> + * This program is free software; you can redistribute it and/or
>>> modify
>>> + * it under the terms of the GNU General Public License as
>>> published by
>>> + * the Free Software Foundation; version 2 of the License.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program. If not, see
>>> <http://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#include <linux/clk.h>
>>> +#include <linux/device.h>
>>> +#include <linux/err.h>
>>> +#include <linux/io.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/of.h>
>>> +#include <linux/module.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/thermal.h>
>>> +
>>> +#include "thermal_core.h"
>>> +
>>> +#define VIRTUAL_SENSORS 2
>>> +
>>> +/* hisi Thermal Sensor Dev Structure */
>>> +struct hisi_thermal_sensor {
>>> + struct hisi_thermal_data *thermal;
>>> + struct thermal_zone_device *tzd;
>>> + void __iomem *sensor_reg;
>>> + unsigned int id;
>>> +};
>>> +
>>> +struct hisi_thermal_data {
>>> + struct platform_device *pdev;
>>> + struct hisi_thermal_sensor *sensors;
>>> + unsigned int range[2];
>>> + unsigned int coef[2];
>>> + unsigned int max_hw_sensor;
>>> +};
>>> +
>>> +static int hisi_thermal_get_temp(void *_sensor, int *temp)
>>> +{
>>> + struct hisi_thermal_sensor *sensor = _sensor;
>>> + struct hisi_thermal_data *data = sensor->thermal;
>>> + unsigned int idx, adc_min, adc_max, max_sensor;
>>> + int val, average = 0, max = 0;
>>> +
>>> + adc_min = data->range[0];
>>> + adc_max = data->range[1];
>>> + max_sensor = data->max_hw_sensor;
>>> +
>>> + if (sensor->id < max_sensor) {
>>> + val = readl(sensor->sensor_reg);
>>> + val = clamp_val(val, adc_min, adc_max);
>>
>> That looks a bit fuzzy. Why not create a get_temp for physical sensor
>> and another one for the virtual? So there will be a clear distinction
>> between both.
> make sense
After thinking about it. I think it virtual sensor should be a separate
driver.
[ ... ]
>> Do we really need a max sensor definition in the DT? Isn't it something
>> we can deduce by looping with platform_get_resource below ?
>>
>> eg.
>>
>> while ((res = platform_get_resource(..., num_sensor++)) {
>> ...
>> }
>>
>> That said, I think we can assume there are 3 sensors always, no?
> If we have three CPU cluster or two cluster share the same sensor in
> future, that number is certain on hi3660
Do you mean, it is always 3 ?
>>> + data->sensors = devm_kzalloc(dev,
>>> + sizeof(*data->sensors) * (max_sensor + VIRTUAL_SENSORS),
>>> + GFP_KERNEL);
>>> + if (IS_ERR(data->sensors)) {
[ ... ]
>>> + }
>>> + }
>>> +
>>> + sensor->id = i;
>>
>> How can we deal with holes in the DT?Do you mean the holes of sensor id?
Yes.
[ ... ]
-- Daniel
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
On Mon, Sep 04, 2017 at 01:06:39PM +0200, Daniel Lezcano wrote:
>
> Hi Kevin,
>
>
> On 04/09/2017 09:56, Wangtao (Kevin, Kirin) wrote:
> >
> >
> > 在 2017/9/1 5:17, Daniel Lezcano 写道:
> >>
> >> Hi Kevin,
> >>
> >>
> >> On 29/08/2017 10:17, Tao Wang wrote:
> >>> From: Tao Wang <[email protected]>
> >>>
> >>> This patch adds the support for thermal sensor of Hi3660 SoC.
> >>
> >> for the Hi3660 SoC thermal sensor.
> >>
> >>> this will register sensors for thermal framework and use device
> >>> tree to bind cooling device.
> >>
> >> Is it possible to give a pointer to some documentation or to describe
> >> the hardware?
> > Yes, there used to be on patch V3, I removed it on V4.
> >>
> >> An explanation of the adc min max coef[] range[] conversion would be
> >> nice.
> > OK
> >>
> >> In addition, having the rational behind the average and the max would be
> >> nice. Do we really need both avg and max as virtual sensor?
> > We only need max currently.
> >>
> >>> Signed-off-by: Tao Wang <[email protected]>
> >>> Signed-off-by: Leo Yan <[email protected]>
> >>> ---
> >>> drivers/thermal/Kconfig | 13 +++
> >>> drivers/thermal/Makefile | 1 +
> >>> drivers/thermal/hisi_tsensor.c | 209
> >>> +++++++++++++++++++++++++++++++++++++++++
> >>
> >>
> >> IMO, we don't need a new file, but merge this code with the current
> >> hisi_thermal.c driver. BTW, the hi6220 has also a tsensor which is
> >> different from this one.
> >>
> >> I suggest to base the hi3660 thermal driver on top of the cleanup I sent
> >> for the hi6220.
> > The tsensor of hi3660 is a different one, merging the code with hi6220
> > will need a lot of change.
>
> Have a look at the hisi_thermal.c at:
>
> https://git.linaro.org/people/daniel.lezcano/linux.git/tree/drivers/thermal/hisi_thermal.c?h=thermal/hikey-4.14
>
> after the cleanup I recently sent.
>
> I'm pretty sure, with a little effort, we can merge both.
>
> Especially if the virtual things is separated.
>
> At the end, what do we do ? Read a register.
Just more input at here. I agree currently Hi3660 thermal driver
is quite similiar with Hi6220, before we wrote a dedicated Hi3660
thermal driver due we used mailbox method rather than shared
memory mode.
If we merge two thermal drivers, this means Hi3660 register layout
should be adjusted as same with Hi6220; I am not sure if this is
feasible and need Kevin to confirm for this.
And does this mean we need provide interrupt mode for Hi3660? Or
we can extend the driver to only support pollig mode?
[...]
Thanks,
Leo Yan
在 2017/9/4 23:06, Leo Yan 写道:
> On Mon, Sep 04, 2017 at 01:06:39PM +0200, Daniel Lezcano wrote:
>>
>> Hi Kevin,
>>
>>
>> On 04/09/2017 09:56, Wangtao (Kevin, Kirin) wrote:
>>>
>>>
>>> 在 2017/9/1 5:17, Daniel Lezcano 写道:
>>>>
>>>> Hi Kevin,
>>>>
>>>>
>>>> On 29/08/2017 10:17, Tao Wang wrote:
>>>>> From: Tao Wang <[email protected]>
>>>>>
>>>>> This patch adds the support for thermal sensor of Hi3660 SoC.
>>>>
>>>> for the Hi3660 SoC thermal sensor.
>>>>
>>>>> this will register sensors for thermal framework and use device
>>>>> tree to bind cooling device.
>>>>
>>>> Is it possible to give a pointer to some documentation or to describe
>>>> the hardware?
>>> Yes, there used to be on patch V3, I removed it on V4.
>>>>
>>>> An explanation of the adc min max coef[] range[] conversion would be
>>>> nice.
>>> OK
>>>>
>>>> In addition, having the rational behind the average and the max would be
>>>> nice. Do we really need both avg and max as virtual sensor?
>>> We only need max currently.
>>>>
>>>>> Signed-off-by: Tao Wang <[email protected]>
>>>>> Signed-off-by: Leo Yan <[email protected]>
>>>>> ---
>>>>> drivers/thermal/Kconfig | 13 +++
>>>>> drivers/thermal/Makefile | 1 +
>>>>> drivers/thermal/hisi_tsensor.c | 209
>>>>> +++++++++++++++++++++++++++++++++++++++++
>>>>
>>>>
>>>> IMO, we don't need a new file, but merge this code with the current
>>>> hisi_thermal.c driver. BTW, the hi6220 has also a tsensor which is
>>>> different from this one.
>>>>
>>>> I suggest to base the hi3660 thermal driver on top of the cleanup I sent
>>>> for the hi6220.
>>> The tsensor of hi3660 is a different one, merging the code with hi6220
>>> will need a lot of change.
>>
>> Have a look at the hisi_thermal.c at:
>>
>> https://git.linaro.org/people/daniel.lezcano/linux.git/tree/drivers/thermal/hisi_thermal.c?h=thermal/hikey-4.14
>>
>> after the cleanup I recently sent.
>>
>> I'm pretty sure, with a little effort, we can merge both.
>>
>> Especially if the virtual things is separated.
>>
>> At the end, what do we do ? Read a register.
>
> Just more input at here. I agree currently Hi3660 thermal driver
> is quite similiar with Hi6220, before we wrote a dedicated Hi3660
> thermal driver due we used mailbox method rather than shared
> memory modeThere are no shared memory mode in thermal driver, I think you mix it up with clock driver.
>
> If we merge two thermal drivers, this means Hi3660 register layout
> should be adjusted as same with Hi6220; I am not sure if this is
> feasible and need Kevin to confirm for this.
Hi3660's register layout is different from Hi6220, and Hi3660's tsensors are configed by MCU, Kernel driver only need to read the temperature.
>
> And does this mean we need provide interrupt mode for Hi3660? Or
> we can extend the driver to only support pollig mode?
>
> [...]
>
> Thanks,
> Leo Yan
>
> .
>