[PATCH v3 0/3] thermal: add thermal sensor driver for Hi3660
From: Tao Wang <kevin.wang...@linaro.org> 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
[PATCH v3 3/3] arm64: dts: register Hi3660's thermal sensor
From: Tao Wang <kevin.wang...@linaro.org> Bind thermal sensor driver for Hi3660. Signed-off-by: Tao Wang <kevin.wang...@linaro.org> Signed-off-by: Leo Yan <leo@linaro.org> --- 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 #include +#include / { compatible = "hisilicon,hi3660"; @@ -848,5 +849,14 @@ _cfg_func>; status = "disabled"; }; + + tsensor: tsensor@FFF3000 { + compatible = "hisilicon,tsensor"; + reg = <0x0 0xfff3 0x0 0x1000>; + offset = <0x1c 0x5c 0x9c>; + coefficients = <165000 (-4)>; + 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 000..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_TEMP0 +#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
[PATCH v3 2/3] thermal: hisilicon: add thermal sensor driver for Hi3660
From: Tao Wang <kevin.wang...@linaro.org> 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 <kevin.wang...@linaro.org> Signed-off-by: Leo Yan <leo@linaro.org> --- 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 000..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 <kevin.wang...@linaro.org> + * Author: Leo Yan <leo@linaro.org> + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "thermal_core.h" + +#define VIRTUAL_SENSORS2 + +/* 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 +
[PATCH v3 1/3] dt-bindings: Document the hi3660 thermal sensor bindings
From: Tao Wang <kevin.wang...@linaro.org> This adds documentation of device tree bindings for the thermal sensor controller of hi3660 SoC. Signed-off-by: Tao Wang <kevin.wang...@linaro.org> --- .../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 000..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 0xfff3 0x0 0x1000>; + offset = <0x1c 0x5c 0x9c>; + coefficients = <165000 (-4)>; + hisi,adc-range = <0x74 0x39A>; + #thermal-sensor-cells = <1>; +}; -- 2.8.1
[PATCH 3/3] arm64: dts: register Hi3660's thermal sensor
Bind thermal sensor driver for Hi3660. Signed-off-by: Tao Wang <kevin.wang...@hisilicon.com> Signed-off-by: Leo Yan <leo@linaro.org> --- 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 0xfff3 0x0 0x1000>; + #thermal-sensor-cells = <1>; + status = "ok"; + }; }; }; -- 1.7.9.5
[PATCH 2/3] thermal: hisilicon: add thermal sensor driver for Hi3660
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 <kevin.wang...@hisilicon.com> Signed-off-by: Leo Yan <leo@linaro.org> --- 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 000..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 <kevin.wang...@hisilicon.com> + * Author: Leo Yan <leo@linaro.org> + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "thermal_core.h" + +#define HW_MAX_SENSORS 4 +#define HISI_MAX_SENSORS 6 +#define SENSOR_MAX 4 +#define SENSOR_AVG 5 + +#define ADC_MIN116 +#define ADC_MAX922 + +/* 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) - 4; + + return 0; +} + +static struct thermal_zone_of_d
[PATCH 1/3] dt-bindings: Document the hi3660 thermal sensor bindings
This adds documentation of device tree bindings for the thermal sensor controller of hi3660 SoC. Signed-off-by: Tao Wang <kevin.wang...@hisilicon.com> --- .../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 000..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 0xfff3 0x0 0x1000>; + #thermal-sensor-cells = <1>; + status = "ok"; +}; -- 1.7.9.5
[Patch v2 3/3] arm64: dts: register Hi3660's thermal sensor
Bind thermal sensor driver for Hi3660. Signed-off-by: Tao Wang <kevin.wang...@hisilicon.com> Signed-off-by: Leo Yan <leo@linaro.org> --- 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 @@ _cfg_func>; status = "disabled"; }; + + tsensor: tsensor { + compatible = "hisilicon,hi3660-thermal"; + reg = <0x0 0xfff3 0x0 0x1000>; + #thermal-sensor-cells = <1>; + }; }; }; -- 1.7.9.5
[Patch v2 1/3] dt-bindings: Document the hi3660 thermal sensor bindings
This adds documentation of device tree bindings for the thermal sensor controller of hi3660 SoC. Signed-off-by: Tao Wang <kevin.wang...@hisilicon.com> --- 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 000..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 0xfff3 0x0 0x1000>; + #thermal-sensor-cells = <1>; +}; -- 1.7.9.5
[Patch v2 2/3] thermal: hisilicon: add thermal sensor driver for Hi3660
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 <kevin.wang...@hisilicon.com> Signed-off-by: Leo Yan <leo@linaro.org> --- 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 000..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 <kevin.wang...@hisilicon.com> + * Author: Leo Yan <leo@linaro.org> + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "thermal_core.h" + +#define HW_MAX_SENSORS 4 +#define HISI_MAX_SENSORS 6 +#define SENSOR_MAX 4 +#define SENSOR_AVG 5 + +#define ADC_MIN116 +#define ADC_MAX922 + +/* 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) - 4; + + return 0;
[PATCH] cpufreq: dt: Add support for hi3660
Add the compatible string for supporting the generic device tree cpufreq-dt driver on Hisilicon's 3660 SoC. Signed-off-by: Tao Wang <kevin.wang...@hisilicon.com> --- drivers/cpufreq/cpufreq-dt-platdev.c |1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 921b4a6..b54e610 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -32,6 +32,7 @@ { .compatible = "arm,integrator-cp", }, { .compatible = "hisilicon,hi6220", }, + { .compatible = "hisilicon,hi3660", }, { .compatible = "fsl,imx27", }, { .compatible = "fsl,imx51", }, -- 1.7.9.5
[Patch v2] cpufreq: dt: Add support for hi3660
Add the compatible string for supporting the generic device tree cpufreq-dt driver on Hisilicon's 3660 SoC. Signed-off-by: Tao Wang <kevin.wang...@hisilicon.com> --- Changes in v2: - changed order according to Viresh's suggestion drivers/cpufreq/cpufreq-dt-platdev.c |1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 921b4a6..1c26292 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -31,6 +31,7 @@ { .compatible = "arm,integrator-ap", }, { .compatible = "arm,integrator-cp", }, + { .compatible = "hisilicon,hi3660", }, { .compatible = "hisilicon,hi6220", }, { .compatible = "fsl,imx27", }, -- 1.7.9.5
[PATCH RFC 2/2] thermal/cpu idle cooling: cpu idle cooling cooperate with cpu cooling
This implements precise cpu thermal control through the cooperation between cpu idle cooling and cpu cooling, avoid frequency decrease if idle injection can achieve the target power limit. This can bring a smoother temperature curve and performance improvement in some case when there are big power gaps between cpu OPPs. Signed-off-by: Tao Wang <kevin.wang...@hisilicon.com> --- drivers/thermal/Kconfig| 17 drivers/thermal/cpu_cooling.c | 31 + drivers/thermal/cpu_idle_cooling.c |5 + include/linux/cpu_idle_cooling.h | 38 4 files changed, 91 insertions(+) create mode 100644 include/linux/cpu_idle_cooling.h diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index f78e85c..ef43d15 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -167,6 +167,23 @@ config CPU_IDLE_THERMAL If you want this support, you should say Y here. +config CPU_THERMAL_COMBO + bool "precise cpu cooling support" + depends on CPU_THERMAL + depends on CPU_IDLE_THERMAL + help + This implements precise cpu thermal control through the cooperation + between idle cooling and cpu cooling. + + This will prevent cpu cooling scaling down cpu frequency when idle + injection can meet the power budget. + + This can bring a smoother temperature curve and performance + improvement in some case when there are big power gaps between cpu + OPPs. + + If you want this support, you should say Y here. + config CLOCK_THERMAL bool "Generic clock cooling support" depends on COMMON_CLK diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index 69d0f43..a81cd92 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -649,6 +650,31 @@ static int cpufreq_state2power(struct thermal_cooling_device *cdev, return ret; } +#ifdef CONFIG_CPU_THERMAL_COMBO +static void idle_cooling_freq_adjust( + struct cpufreq_cooling_device *cpufreq_device, + u32 power, unsigned int *target_freq) +{ + unsigned long target_load, max_idle_ratio; + unsigned int idle_freq; + s32 cur_dyn_power; + + max_idle_ratio = get_max_idle_state(_device->allowed_cpus); + cur_dyn_power = power * 100 / (100 - max_idle_ratio); + idle_freq = cpu_power_to_freq(cpufreq_device, cur_dyn_power); + + cur_dyn_power = cpu_freq_to_power(cpufreq_device, idle_freq); + target_load = (power * 100) / cur_dyn_power; + if (target_load < 100 + && ((idle_freq * target_load) >= ((*target_freq) * 100))) { + *target_freq = idle_freq; + } else { + target_load = 100; + } + set_idle_state(_device->allowed_cpus, 100 - target_load); +} +#endif + /** * cpufreq_power2state() - convert power to a cooling device state * @cdev: _cooling_device pointer @@ -696,6 +722,11 @@ static int cpufreq_power2state(struct thermal_cooling_device *cdev, normalised_power = (dyn_power * 100) / last_load; target_freq = cpu_power_to_freq(cpufreq_device, normalised_power); +#ifdef CONFIG_CPU_THERMAL_COMBO + idle_cooling_freq_adjust(cpufreq_device, + normalised_power, _freq); +#endif + *state = cpufreq_cooling_get_level(cpu, target_freq); if (*state == THERMAL_CSTATE_INVALID) { dev_err_ratelimited(>device, diff --git a/drivers/thermal/cpu_idle_cooling.c b/drivers/thermal/cpu_idle_cooling.c index 89a15c5..4a1844d 100644 --- a/drivers/thermal/cpu_idle_cooling.c +++ b/drivers/thermal/cpu_idle_cooling.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +36,11 @@ #include #include +#ifdef CONFIG_CPU_THERMAL_COMBO +#define MAX_TARGET_RATIO (20U) +#else #define MAX_TARGET_RATIO (50U) +#endif #define DEFAULT_WINDOW_SIZE(1) #define DEFAULT_DURATION_JIFFIES (20) diff --git a/include/linux/cpu_idle_cooling.h b/include/linux/cpu_idle_cooling.h new file mode 100644 index 000..da5f19a --- /dev/null +++ b/include/linux/cpu_idle_cooling.h @@ -0,0 +1,38 @@ +/* + * linux/drivers/thermal/cpu_idle_cooling.h + * + * Copyright (C) 2017 Tao Wang <kevin.wang...@hisilicon.com> + * + * 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 PUR
[PATCH RFC 1/2] thermal/cpu idle cooling: Introduce cpu idle cooling driver
cpu idle cooling driver performs synchronized idle injection across all cpu in same cluster, offers a new method to cooling down cpu, that is similar to intel_power_clamp driver, but is basically designed for ARM platform. Each cluster has its own idle cooling device, each core has its own idle injection thread, idle injection thread use play_idle to enter idle. In order to reach deepest idle state, all cores are aligned by jiffies. the injected idle ratio can be controlled through cooling device interface. Signed-off-by: Tao Wang <kevin.wang...@hisilicon.com> --- drivers/thermal/Kconfig| 13 + drivers/thermal/Makefile |3 + drivers/thermal/cpu_idle_cooling.c | 648 3 files changed, 664 insertions(+) create mode 100644 drivers/thermal/cpu_idle_cooling.c diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index b5b5fac..f78e85c 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -154,6 +154,19 @@ config CPU_THERMAL If you want this support, you should say Y here. +config CPU_IDLE_THERMAL + tristate "generic cpu idle cooling support" + depends on CPU_FREQ + help + This implements the generic cpu cooling mechanism through idle + injection. + + This will throttle cpu by injecting specified idle time in + a fixed cycle. All cpu in same cluster will enter idle synchronously + to reach deepest idle state when injecting idle. + + If you want this support, you should say Y here. + config CLOCK_THERMAL bool "Generic clock cooling support" depends on COMMON_CLK diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 094d703..a4db66e 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -26,6 +26,9 @@ thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o # devfreq cooling thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o +# cpu idle cooling +obj-$(CONFIG_CPU_IDLE_THERMAL) += cpu_idle_cooling.o + # platform thermal drivers obj-y += broadcom/ obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o diff --git a/drivers/thermal/cpu_idle_cooling.c b/drivers/thermal/cpu_idle_cooling.c new file mode 100644 index 000..89a15c5 --- /dev/null +++ b/drivers/thermal/cpu_idle_cooling.c @@ -0,0 +1,648 @@ +/* + * linux/drivers/thermal/cpu_idle_cooling.c + * + * Copyright (C) 2017 Tao Wang <kevin.wang...@hisilicon.com> + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_TARGET_RATIO (50U) + +#define DEFAULT_WINDOW_SIZE(1) +#define DEFAULT_DURATION_JIFFIES (20) + +struct cpu_idle_cooling_device { + int id; + struct thermal_cooling_device *cooling_dev; + wait_queue_head_t wait_queue; + + /* The cpu assigned to collect stat and update +* control parameters. default to BSP but BSP +* can be offlined. +*/ + unsigned long control_cpu; + + unsigned int set_target_ratio; + unsigned int current_ratio; + unsigned int control_ratio; + unsigned int duration; + unsigned int window_size; + + cpumask_var_t related_cpus; + cpumask_var_t injected_cpus; + struct list_head node; + bool should_skip; + bool clamping; +}; + +static LIST_HEAD(cpu_idle_cooling_dev_list); +static DEFINE_PER_CPU(struct task_struct *, idle_injection_thread_ptr); +static DEFINE_MUTEX(cpu_idle_cooling_lock); + +unsigned long idle_time[NR_CPUS] = {0}; +unsigned long time_stamp[NR_CPUS] = {0}; +static enum cpuhp_state hp_state; + +#define STORE_PARAM(param, min, max) \ +static ssize_t store_##param(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + unsigned int new_value; \ + struct thermal_cooling_device *cdev;\ + struct cpu
[PATCH 6/9] thermal/drivers/hisi: add support for multi temp threshold
From: Kevin Wangtaotsensor may have multi alarm levels, so we can support more trip point interrupt. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 21 - 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index f9d9fd6..718376b 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -46,10 +46,12 @@ #define HI6220_DEFAULT_SENSOR 2 +#define MAX_THRES_NUM 2 + struct hisi_thermal_sensor { struct thermal_zone_device *tzd; uint32_t id; - uint32_t thres_temp; + uint32_t thres_temp[MAX_THRES_NUM]; }; struct hisi_thermal_data { @@ -244,7 +246,7 @@ static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) hi6220_thermal_set_lag(data->regs, HI6220_TEMP_LAG); /* enable for interrupt */ - hi6220_thermal_alarm_set(data->regs, sensor->thres_temp); + hi6220_thermal_alarm_set(data->regs, sensor->thres_temp[0]); hi6220_thermal_reset_set(data->regs, HI6220_TEMP_RESET); @@ -303,7 +305,7 @@ static int hisi_thermal_get_temp(void *__data, int *temp) *temp = data->get_temp(data); dev_dbg(>pdev->dev, "id=%d, temp=%d, thres=%d\n", - sensor->id, *temp, sensor->thres_temp); + sensor->id, *temp, sensor->thres_temp[0]); return 0; } @@ -322,16 +324,16 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) hisi_thermal_get_temp(data, ); - if (temp >= sensor->thres_temp) { + if (temp >= sensor->thres_temp[0]) { dev_crit(>pdev->dev, "THERMAL ALARM: %d > %d\n", -temp, sensor->thres_temp); +temp, sensor->thres_temp[0]); thermal_zone_device_update(data->sensor.tzd, THERMAL_EVENT_UNSPECIFIED); } else { dev_crit(>pdev->dev, "THERMAL ALARM stopped: %d < %d\n", -temp, sensor->thres_temp); +temp, sensor->thres_temp[0]); } return IRQ_HANDLED; @@ -341,7 +343,7 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, struct hisi_thermal_data *data, struct hisi_thermal_sensor *sensor) { - int ret, i; + int ret, i, thres_idx = 0; const struct thermal_trip *trip; sensor->tzd = devm_thermal_zone_of_sensor_register(>dev, @@ -359,8 +361,9 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, for (i = 0; i < of_thermal_get_ntrips(sensor->tzd); i++) { if (trip[i].type == THERMAL_TRIP_PASSIVE) { - sensor->thres_temp = trip[i].temperature; - break; + sensor->thres_temp[thres_idx++] = trip[i].temperature; + if (thres_idx >= MAX_THRES_NUM) + break; } } -- 2.8.1
[PATCH 2/9] thermal/drivers/hisi: use round up step value
From: Kevin WangtaoUse round up divide to ensure the programmed value of threshold and lag not less than we set, and in order to keep the accuracy while using round up divide, the step value should also be a round up value. Then there is no need to use hisi_thermal_round_temp. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 22 -- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index c43e3df..c8b651d 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -40,7 +40,7 @@ #define HISI_TEMP_BASE (-6) #define HISI_TEMP_RESET(10) -#define HISI_TEMP_STEP (784) +#define HISI_TEMP_STEP (785) #define HISI_TEMP_LAG (3500) #define HISI_MAX_SENSORS 4 @@ -63,19 +63,19 @@ struct hisi_thermal_data { /* * The temperature computation on the tsensor is as follow: * Unit: millidegree Celsius - * Step: 255/200 (0.7843) + * Step: 200/255 (0.7843) * Temperature base: -60??C * - * The register is programmed in temperature steps, every step is 784 + * The register is programmed in temperature steps, every step is 785 * millidegree and begins at -60 000 m??C * * The temperature from the steps: * - * Temp = TempBase + (steps x 784) + * Temp = TempBase + (steps x 785) * * and the steps from the temperature: * - * steps = (Temp - TempBase) / 784 + * steps = (Temp - TempBase) / 785 * */ static inline int hisi_thermal_step_to_temp(int step) @@ -85,13 +85,7 @@ static inline int hisi_thermal_step_to_temp(int step) static inline int hisi_thermal_temp_to_step(int temp) { - return (temp - HISI_TEMP_BASE) / HISI_TEMP_STEP; -} - -static inline int hisi_thermal_round_temp(int temp) -{ - return hisi_thermal_step_to_temp( - hisi_thermal_temp_to_step(temp)); + return DIV_ROUND_UP(temp - HISI_TEMP_BASE, HISI_TEMP_STEP); } /* @@ -127,7 +121,7 @@ static inline int hisi_thermal_round_temp(int temp) */ static inline void hisi_thermal_set_lag(void __iomem *addr, int value) { - writel((value / HISI_TEMP_STEP) & 0x1F, addr + TEMP0_LAG); + writel(DIV_ROUND_UP(value, HISI_TEMP_STEP) & 0x1F, addr + TEMP0_LAG); } static inline void hisi_thermal_alarm_clear(void __iomem *addr, int value) @@ -274,7 +268,7 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, for (i = 0; i < of_thermal_get_ntrips(sensor->tzd); i++) { if (trip[i].type == THERMAL_TRIP_PASSIVE) { - sensor->thres_temp = hisi_thermal_round_temp(trip[i].temperature); + sensor->thres_temp = trip[i].temperature; break; } } -- 2.8.1
[PATCH 8/9] thermal/drivers/hisi: add support for hi3660 SoC
From: Kevin WangtaoThis patch adds the support for thermal sensor of Hi3660 SoC. Hi3660 tsensor support alarm interrupt and have three configurable alarm thresholds, it also has a configurable hysteresis interval, interrupt will be triggered when temperature rise above the alarm threshold or fall below the hysteresis threshold. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 146 - 1 file changed, 145 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 718376b..133238a 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -39,12 +39,24 @@ #define HI6220_TEMP0_RST_MSK (0x1C) #define HI6220_TEMP0_VALUE (0x28) +#define HI3660_OFFSET(chan)((chan) * 0x40) +#define HI3660_TEMP(chan) (HI3660_OFFSET(chan) + 0x1C) +#define HI3660_TH(chan)(HI3660_OFFSET(chan) + 0x20) +#define HI3660_LAG(chan) (HI3660_OFFSET(chan) + 0x28) +#define HI3660_INT_EN(chan)(HI3660_OFFSET(chan) + 0x2C) +#define HI3660_INT_CLR(chan) (HI3660_OFFSET(chan) + 0x30) + #define HI6220_TEMP_BASE (-6) #define HI6220_TEMP_RESET (10) #define HI6220_TEMP_STEP (785) #define HI6220_TEMP_LAG(3500) +#define HI3660_TEMP_BASE (-63780) +#define HI3660_TEMP_STEP (205) +#define HI3660_TEMP_LAG(4000) + #define HI6220_DEFAULT_SENSOR 2 +#define HI3660_DEFAULT_SENSOR 1 #define MAX_THRES_NUM 2 @@ -96,6 +108,24 @@ static inline int hi6220_thermal_temp_to_step(int temp) } /* + * for Hi3660, + * Step: 189/922 (0.205) + * Temperature base: -63.780??C + * + * The register is programmed in temperature steps, every step is 205 + * millidegree and begins at -63 780 m??C + */ +static inline int hi3660_thermal_step_to_temp(int step) +{ + return HI3660_TEMP_BASE + step * HI3660_TEMP_STEP; +} + +static inline int hi3660_thermal_temp_to_step(int temp) +{ + return DIV_ROUND_UP(temp - HI3660_TEMP_BASE, HI3660_TEMP_STEP); +} + +/* * The lag register contains 5 bits encoding the temperature in steps. * * Each time the temperature crosses the threshold boundary, an @@ -169,6 +199,45 @@ static inline int hi6220_thermal_get_temperature(void __iomem *addr) } /* + * [0:6] lag register + * + * The temperature is coded in steps, cf. HI3660_TEMP_STEP. + * + * Min : 0x00 : 0.0 ??C + * Max : 0x7F : 26.0 ??C + * + */ +static inline void hi3660_thermal_set_lag(void __iomem *addr, + int id, int value) +{ + writel(DIV_ROUND_UP(value, HI3660_TEMP_STEP) & 0x7F, + addr + HI3660_LAG(id)); +} + +static inline void hi3660_thermal_alarm_clear(void __iomem *addr, + int id, int value) +{ + writel(value, addr + HI3660_INT_CLR(id)); +} + +static inline void hi3660_thermal_alarm_enable(void __iomem *addr, + int id, int value) +{ + writel(value, addr + HI3660_INT_EN(id)); +} + +static inline void hi3660_thermal_alarm_set(void __iomem *addr, + int id, int value) +{ + writel(value, addr + HI3660_TH(id)); +} + +static inline int hi3660_thermal_get_temperature(void __iomem *addr, int id) +{ + return hi3660_thermal_step_to_temp(readl(addr + HI3660_TEMP(id))); +} + +/* * Temperature configuration register - Sensor selection * * Bits [19:12] @@ -206,11 +275,22 @@ static int hi6220_thermal_irq_handler(struct hisi_thermal_data *data) return 0; } +static int hi3660_thermal_irq_handler(struct hisi_thermal_data *data) +{ + hi3660_thermal_alarm_clear(data->regs, data->sensor.id, 1); + return 0; +} + static int hi6220_thermal_get_temp(struct hisi_thermal_data *data) { return hi6220_thermal_get_temperature(data->regs); } +static int hi3660_thermal_get_temp(struct hisi_thermal_data *data) +{ + return hi3660_thermal_get_temperature(data->regs, data->sensor.id); +} + static int hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) { /* disable sensor module */ @@ -222,6 +302,13 @@ static int hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) return 0; } +static int hi3660_thermal_disable_sensor(struct hisi_thermal_data *data) +{ + /* disable sensor module */ + hi3660_thermal_alarm_enable(data->regs, data->sensor.id, 0); + return 0; +} + static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) { struct hisi_thermal_sensor *sensor = >sensor; @@ -260,6 +347,29 @@ static int hi6220_thermal_enable_sensor(struct
[PATCH 5/9] thermal/drivers/hisi: perpare to add support for other hisi platform
From: Kevin WangtaoFor platform compatibility, add tsensor operation function pointer to thermal data, and each platform has its own probe function to register proper tsensor operation function to the pointer, platform related resource request are also implemented in the platform probe function. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 135 +++-- 1 file changed, 89 insertions(+), 46 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 4635839..f9d9fd6 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "thermal_core.h" @@ -30,7 +31,7 @@ #define HI6220_TEMP0_TH(0x4) #define HI6220_TEMP0_RST_TH(0x8) #define HI6220_TEMP0_CFG (0xC) -#define HI6220_TEMP0_CFG_SS_MSK(0xF000) +#define HI6220_TEMP0_CFG_SS_MSK(0xF000) #define HI6220_TEMP0_CFG_HDAK_MSK (0x30) #define HI6220_TEMP0_EN(0x10) #define HI6220_TEMP0_INT_EN(0x14) @@ -41,7 +42,7 @@ #define HI6220_TEMP_BASE (-6) #define HI6220_TEMP_RESET (10) #define HI6220_TEMP_STEP (785) -#define HI6220_TEMP_LAG(3500) +#define HI6220_TEMP_LAG(3500) #define HI6220_DEFAULT_SENSOR 2 @@ -52,6 +53,10 @@ struct hisi_thermal_sensor { }; struct hisi_thermal_data { + int (*get_temp)(struct hisi_thermal_data *data); + int (*enable_sensor)(struct hisi_thermal_data *data); + int (*disable_sensor)(struct hisi_thermal_data *data); + int (*irq_handler)(struct hisi_thermal_data *data); struct platform_device *pdev; struct clk *clk; struct hisi_thermal_sensor sensor; @@ -59,6 +64,7 @@ struct hisi_thermal_data { int irq; }; + /* * The temperature computation on the tsensor is as follow: * Unit: millidegree Celsius @@ -192,7 +198,18 @@ static inline void hi6220_thermal_hdak_set(void __iomem *addr, int value) (value << 4), addr + HI6220_TEMP0_CFG); } -static void hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) +static int hi6220_thermal_irq_handler(struct hisi_thermal_data *data) +{ + hi6220_thermal_alarm_clear(data->regs, 1); + return 0; +} + +static int hi6220_thermal_get_temp(struct hisi_thermal_data *data) +{ + return hi6220_thermal_get_temperature(data->regs); +} + +static int hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) { /* disable sensor module */ hi6220_thermal_enable(data->regs, 0); @@ -200,9 +217,9 @@ static void hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) hi6220_thermal_reset_enable(data->regs, 0); clk_disable_unprepare(data->clk); + return 0; } - static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) { struct hisi_thermal_sensor *sensor = >sensor; @@ -240,12 +257,50 @@ static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) return 0; } + +static int hi6220_thermal_probe(struct hisi_thermal_data *data) +{ + struct platform_device *pdev = data->pdev; + struct device *dev = >dev; + struct resource *res; + int ret; + + data->get_temp = hi6220_thermal_get_temp; + data->enable_sensor = hi6220_thermal_enable_sensor; + data->disable_sensor = hi6220_thermal_disable_sensor; + data->irq_handler = hi6220_thermal_irq_handler; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(data->regs)) { + dev_err(dev, "failed to get io address\n"); + return PTR_ERR(data->regs); + } + + data->clk = devm_clk_get(dev, "thermal_clk"); + if (IS_ERR(data->clk)) { + ret = PTR_ERR(data->clk); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get thermal clk: %d\n", ret); + return ret; + } + + data->irq = platform_get_irq(pdev, 0); + if (data->irq < 0) + return data->irq; + + data->sensor.id = HI6220_DEFAULT_SENSOR; + + return 0; +} + + static int hisi_thermal_get_temp(void *__data, int *temp) { struct hisi_thermal_data *data = __data; struct hisi_thermal_sensor *sensor = >sensor; - *temp = hi6220_thermal_get_temperature(data->regs); + *temp = data->get_temp(data); dev_dbg(>pdev->dev, "id=%d, temp=%d, thres=%d\n", sensor->id, *temp, sensor->thres_temp); @@ -263,7 +318,7 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq,
[PATCH 1/9] thermal/drivers/hisi: move clk operation to related function
From: Kevin WangtaoThe sensor's clock is enabled and disabled outside of the probe and disable function. Moving the corresponding action in the hisi_thermal_setup() and hisi_thermal_disable_sensor(), factors out some lines of code and makes the code more symmetric. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 29 + 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 39f4627..c43e3df 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -203,6 +203,8 @@ static void hisi_thermal_disable_sensor(struct hisi_thermal_data *data) hisi_thermal_enable(data->regs, 0); hisi_thermal_alarm_enable(data->regs, 0); hisi_thermal_reset_enable(data->regs, 0); + + clk_disable_unprepare(data->clk); } static int hisi_thermal_get_temp(void *__data, int *temp) @@ -297,9 +299,13 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, static int hisi_thermal_setup(struct hisi_thermal_data *data) { - struct hisi_thermal_sensor *sensor; + struct hisi_thermal_sensor *sensor = >sensor; + int ret; - sensor = >sensor; + /* enable clock for tsensor */ + ret = clk_prepare_enable(data->clk); + if (ret) + return ret; /* disable module firstly */ hisi_thermal_reset_enable(data->regs, 0); @@ -363,13 +369,6 @@ static int hisi_thermal_probe(struct platform_device *pdev) return ret; } - /* enable clock for thermal */ - ret = clk_prepare_enable(data->clk); - if (ret) { - dev_err(>dev, "failed to enable thermal clk: %d\n", ret); - return ret; - } - ret = hisi_thermal_register_sensor(pdev, data, >sensor, HISI_DEFAULT_SENSOR); @@ -405,7 +404,6 @@ static int hisi_thermal_remove(struct platform_device *pdev) hisi_thermal_toggle_sensor(sensor, false); hisi_thermal_disable_sensor(data); - clk_disable_unprepare(data->clk); return 0; } @@ -417,23 +415,14 @@ static int hisi_thermal_suspend(struct device *dev) hisi_thermal_disable_sensor(data); - clk_disable_unprepare(data->clk); - return 0; } static int hisi_thermal_resume(struct device *dev) { struct hisi_thermal_data *data = dev_get_drvdata(dev); - int ret; - ret = clk_prepare_enable(data->clk); - if (ret) - return ret; - - hisi_thermal_setup(data); - - return 0; + return hisi_thermal_setup(data); } #endif -- 2.8.1
[PATCH 7/9] dt-bindings: Document the hi3660 thermal sensor binding
From: Kevin WangtaoThis adds documentation of device tree bindings for the thermal sensor controller of hi3660 SoC. Signed-off-by: Kevin Wangtao --- Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt | 9 + 1 file changed, 9 insertions(+) diff --git a/Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt b/Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt index d48fc52..cef716a 100644 --- a/Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt @@ -13,6 +13,7 @@ Example : +for Hi6220: tsensor: tsensor@0,f7030700 { compatible = "hisilicon,tsensor"; reg = <0x0 0xf7030700 0x0 0x1000>; @@ -21,3 +22,11 @@ Example : clock-names = "thermal_clk"; #thermal-sensor-cells = <1>; } + +for Hi3660: + tsensor: tsensor@fff3 { + compatible = "hisilicon,hi3660-tsensor"; + reg = <0x0 0xfff3 0x0 0x1000>; + interrupts = ; + #thermal-sensor-cells = <1>; + }; -- 2.8.1
[PATCH 3/9] thermal/drivers/hisi: put platform code together
From: Kevin Wangtaoreorganize code for follow-up patch, there is no functional change here. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 76 +- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index c8b651d..96904b4 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -201,6 +201,44 @@ static void hisi_thermal_disable_sensor(struct hisi_thermal_data *data) clk_disable_unprepare(data->clk); } + +static int hisi_thermal_setup(struct hisi_thermal_data *data) +{ + struct hisi_thermal_sensor *sensor = >sensor; + int ret; + + /* enable clock for tsensor */ + ret = clk_prepare_enable(data->clk); + if (ret) + return ret; + + /* disable module firstly */ + hisi_thermal_reset_enable(data->regs, 0); + hisi_thermal_enable(data->regs, 0); + + /* select sensor id */ + hisi_thermal_sensor_select(data->regs, sensor->id); + + /* setting the hdak time */ + hisi_thermal_hdak_set(data->regs, 0); + + /* setting lag value between current temp and the threshold */ + hisi_thermal_set_lag(data->regs, HISI_TEMP_LAG); + + /* enable for interrupt */ + hisi_thermal_alarm_set(data->regs, sensor->thres_temp); + + hisi_thermal_reset_set(data->regs, HISI_TEMP_RESET); + + /* enable module */ + hisi_thermal_reset_enable(data->regs, 1); + hisi_thermal_enable(data->regs, 1); + + hisi_thermal_alarm_clear(data->regs, 0); + hisi_thermal_alarm_enable(data->regs, 1); + + return 0; +} static int hisi_thermal_get_temp(void *__data, int *temp) { struct hisi_thermal_data *data = __data; @@ -291,44 +329,6 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); } -static int hisi_thermal_setup(struct hisi_thermal_data *data) -{ - struct hisi_thermal_sensor *sensor = >sensor; - int ret; - - /* enable clock for tsensor */ - ret = clk_prepare_enable(data->clk); - if (ret) - return ret; - - /* disable module firstly */ - hisi_thermal_reset_enable(data->regs, 0); - hisi_thermal_enable(data->regs, 0); - - /* select sensor id */ - hisi_thermal_sensor_select(data->regs, sensor->id); - - /* setting the hdak time */ - hisi_thermal_hdak_set(data->regs, 0); - - /* setting lag value between current temp and the threshold */ - hisi_thermal_set_lag(data->regs, HISI_TEMP_LAG); - - /* enable for interrupt */ - hisi_thermal_alarm_set(data->regs, sensor->thres_temp); - - hisi_thermal_reset_set(data->regs, HISI_TEMP_RESET); - - /* enable module */ - hisi_thermal_reset_enable(data->regs, 1); - hisi_thermal_enable(data->regs, 1); - - hisi_thermal_alarm_clear(data->regs, 0); - hisi_thermal_alarm_enable(data->regs, 1); - - return 0; -} - static int hisi_thermal_probe(struct platform_device *pdev) { struct hisi_thermal_data *data; -- 2.8.1
[PATCH 9/9] arm64: dts: register Hi3660's thermal sensor
From: Kevin Wangtaoadd binding for tsensor on H3660, this tsensor is used for SoC thermal control, it supports alarm interrupt. Signed-off-by: Kevin Wangtao --- arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 8 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi index b7a90d6..ae90991 100644 --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi @@ -978,5 +978,13 @@ clocks = <_ctrl HI3660_OSC32K>; clock-names = "apb_pclk"; }; + + tsensor: tsensor@fff3 { + compatible = "hisilicon,hi3660-tsensor"; + reg = <0x0 0xfff3 0x0 0x1000>; + interrupts = ; + #thermal-sensor-cells = <1>; + }; + }; }; -- 2.8.1
[PATCH 4/9] thermal/drivers/hisi: add platform prefix to function name
From: Kevin Wangtaoreorganize code for follow-up patch, there is no functional change here. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 145 + 1 file changed, 73 insertions(+), 72 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 96904b4..4635839 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -26,25 +26,24 @@ #include "thermal_core.h" -#define TEMP0_LAG (0x0) -#define TEMP0_TH (0x4) -#define TEMP0_RST_TH (0x8) -#define TEMP0_CFG (0xC) -#define TEMP0_CFG_SS_MSK (0xF000) -#define TEMP0_CFG_HDAK_MSK (0x30) -#define TEMP0_EN (0x10) -#define TEMP0_INT_EN (0x14) -#define TEMP0_INT_CLR (0x18) -#define TEMP0_RST_MSK (0x1C) -#define TEMP0_VALUE(0x28) - -#define HISI_TEMP_BASE (-6) -#define HISI_TEMP_RESET(10) -#define HISI_TEMP_STEP (785) -#define HISI_TEMP_LAG (3500) - -#define HISI_MAX_SENSORS 4 -#define HISI_DEFAULT_SENSOR2 +#define HI6220_TEMP0_LAG (0x0) +#define HI6220_TEMP0_TH(0x4) +#define HI6220_TEMP0_RST_TH(0x8) +#define HI6220_TEMP0_CFG (0xC) +#define HI6220_TEMP0_CFG_SS_MSK(0xF000) +#define HI6220_TEMP0_CFG_HDAK_MSK (0x30) +#define HI6220_TEMP0_EN(0x10) +#define HI6220_TEMP0_INT_EN(0x14) +#define HI6220_TEMP0_INT_CLR (0x18) +#define HI6220_TEMP0_RST_MSK (0x1C) +#define HI6220_TEMP0_VALUE (0x28) + +#define HI6220_TEMP_BASE (-6) +#define HI6220_TEMP_RESET (10) +#define HI6220_TEMP_STEP (785) +#define HI6220_TEMP_LAG(3500) + +#define HI6220_DEFAULT_SENSOR 2 struct hisi_thermal_sensor { struct thermal_zone_device *tzd; @@ -78,14 +77,14 @@ struct hisi_thermal_data { * steps = (Temp - TempBase) / 785 * */ -static inline int hisi_thermal_step_to_temp(int step) +static inline int hi6220_thermal_step_to_temp(int step) { - return HISI_TEMP_BASE + (step * HISI_TEMP_STEP); + return HI6220_TEMP_BASE + (step * HI6220_TEMP_STEP); } -static inline int hisi_thermal_temp_to_step(int temp) +static inline int hi6220_thermal_temp_to_step(int temp) { - return DIV_ROUND_UP(temp - HISI_TEMP_BASE, HISI_TEMP_STEP); + return DIV_ROUND_UP(temp - HI6220_TEMP_BASE, HI6220_TEMP_STEP); } /* @@ -112,51 +111,53 @@ static inline int hisi_thermal_temp_to_step(int temp) * * [0:4] : lag register * - * The temperature is coded in steps, cf. HISI_TEMP_STEP. + * The temperature is coded in steps, cf. HI6220_TEMP_STEP. * * Min : 0x00 : 0.0 ??C * Max : 0x1F : 24.3 ??C * * The 'value' parameter is in milliCelsius. */ -static inline void hisi_thermal_set_lag(void __iomem *addr, int value) +static inline void hi6220_thermal_set_lag(void __iomem *addr, int value) { - writel(DIV_ROUND_UP(value, HISI_TEMP_STEP) & 0x1F, addr + TEMP0_LAG); + writel(DIV_ROUND_UP(value, HI6220_TEMP_STEP) & 0x1F, + addr + HI6220_TEMP0_LAG); } -static inline void hisi_thermal_alarm_clear(void __iomem *addr, int value) +static inline void hi6220_thermal_alarm_clear(void __iomem *addr, int value) { - writel(value, addr + TEMP0_INT_CLR); + writel(value, addr + HI6220_TEMP0_INT_CLR); } -static inline void hisi_thermal_alarm_enable(void __iomem *addr, int value) +static inline void hi6220_thermal_alarm_enable(void __iomem *addr, int value) { - writel(value, addr + TEMP0_INT_EN); + writel(value, addr + HI6220_TEMP0_INT_EN); } -static inline void hisi_thermal_alarm_set(void __iomem *addr, int temp) +static inline void hi6220_thermal_alarm_set(void __iomem *addr, int temp) { - writel(hisi_thermal_temp_to_step(temp) | 0x0FF00, addr + TEMP0_TH); + writel(hi6220_thermal_temp_to_step(temp) | 0x0FF00, + addr + HI6220_TEMP0_TH); } -static inline void hisi_thermal_reset_set(void __iomem *addr, int temp) +static inline void hi6220_thermal_reset_set(void __iomem *addr, int temp) { - writel(hisi_thermal_temp_to_step(temp), addr + TEMP0_RST_TH); + writel(hi6220_thermal_temp_to_step(temp), addr + HI6220_TEMP0_RST_TH); } -static inline void hisi_thermal_reset_enable(void __iomem *addr, int value) +static inline void hi6220_thermal_reset_enable(void __iomem *addr, int value) { - writel(value, addr + TEMP0_RST_MSK); + writel(value, addr +
[PATCH 0/9] add support for Hi3660 tsensor
From: Kevin WangtaoThis patchset reorganize hisi thermal driver and make it both support Hi6220 and Hi3660. This patchset is based on Daniel thermal patch V2. https://lkml.org/lkml/2017/9/4/432 Kevin Wangtao (9): thermal/drivers/hisi: move clk operation to related function thermal/drivers/hisi: use round up step value thermal/drivers/hisi: put platform code together thermal/drivers/hisi: add platform prefix to function name thermal/drivers/hisi: perpare to add support for other hisi platform thermal/drivers/hisi: add support for multi temp threshold dt-bindings: Document the hi3660 thermal sensor binding thermal/drivers/hisi: add support for hi3660 SoC arm64: dts: register Hi3660's thermal sensor .../bindings/thermal/hisilicon-thermal.txt | 9 + arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 8 + drivers/thermal/hisi_thermal.c | 494 ++--- 3 files changed, 351 insertions(+), 160 deletions(-) -- 2.8.1
[PATCH v4 0/3] thermal: add thermal sensor driver for Hi3660
From: Tao Wang <kevin.wang...@linaro.org> 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
[PATCH v4 3/3] arm64: dts: register Hi3660's thermal sensor
From: Tao Wang <kevin.wang...@linaro.org> Bind thermal sensor driver for Hi3660. Signed-off-by: Tao Wang <kevin.wang...@linaro.org> Signed-off-by: Leo Yan <leo@linaro.org> --- 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 #include +#include / { compatible = "hisilicon,hi3660"; @@ -848,5 +849,18 @@ _cfg_func>; status = "disabled"; }; + + tsensor: tsensor@fff3 { + 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,coef = <165000 (-4)>; + 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 000..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_TEMP0 +#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
[PATCH v4 2/3] thermal: hisilicon: add thermal sensor driver for Hi3660
From: Tao Wang <kevin.wang...@linaro.org> 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 <kevin.wang...@linaro.org> Signed-off-by: Leo Yan <leo@linaro.org> --- 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 000..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 <kevin.wang...@linaro.org> + * Author: Leo Yan <leo@linaro.org> + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "thermal_core.h" + +#define VIRTUAL_SENSORS2 + +/* 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) +
[PATCH v4 1/3] dt-bindings: Document the hi3660 thermal sensor bindings
From: Tao Wang <kevin.wang...@linaro.org> This adds documentation of device tree bindings for the thermal sensor controller of hi3660 SoC. Signed-off-by: Tao Wang <kevin.wang...@linaro.org> --- .../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 000..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@fff3 { + 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,coef = <165000 (-4)>; + hisi,adc-range = <0x74 0x39A>; + #thermal-sensor-cells = <1>; +}; -- 2.8.1
[PATCH] thermal/drivers/hisi: disable multi alarm support for hi3660 SoC
From: Kevin Wangtaomulti alarm interrupt forced a re-trigger of power_allocator_throttle which changes the PID's actual sampling rate, this isn't optimal for IPA, it is best to disable multi alarm support now and sort out this issue later. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 133238a..3b74c12 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -360,7 +360,6 @@ static int hi3660_thermal_enable_sensor(struct hisi_thermal_data *data) /* set interrupt threshold */ value = hi3660_thermal_temp_to_step(sensor->thres_temp[0]); - value |= hi3660_thermal_temp_to_step(sensor->thres_temp[1]) << 10; hi3660_thermal_alarm_set(data->regs, sensor->id, value); /* enable interrupt */ -- 2.8.1
[PATCH] thermal/drivers/hisi: disable multi alarm support for hi3660 SoC
From: Kevin Wangtao multi alarm interrupt forced a re-trigger of power_allocator_throttle which changes the PID's actual sampling rate, this isn't optimal for IPA, it is best to disable multi alarm support now and sort out this issue later. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 133238a..3b74c12 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -360,7 +360,6 @@ static int hi3660_thermal_enable_sensor(struct hisi_thermal_data *data) /* set interrupt threshold */ value = hi3660_thermal_temp_to_step(sensor->thres_temp[0]); - value |= hi3660_thermal_temp_to_step(sensor->thres_temp[1]) << 10; hi3660_thermal_alarm_set(data->regs, sensor->id, value); /* enable interrupt */ -- 2.8.1
[PATCH 0/9] add support for Hi3660 tsensor
From: Kevin Wangtao This patchset reorganize hisi thermal driver and make it both support Hi6220 and Hi3660. This patchset is based on Daniel thermal patch V2. https://lkml.org/lkml/2017/9/4/432 Kevin Wangtao (9): thermal/drivers/hisi: move clk operation to related function thermal/drivers/hisi: use round up step value thermal/drivers/hisi: put platform code together thermal/drivers/hisi: add platform prefix to function name thermal/drivers/hisi: perpare to add support for other hisi platform thermal/drivers/hisi: add support for multi temp threshold dt-bindings: Document the hi3660 thermal sensor binding thermal/drivers/hisi: add support for hi3660 SoC arm64: dts: register Hi3660's thermal sensor .../bindings/thermal/hisilicon-thermal.txt | 9 + arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 8 + drivers/thermal/hisi_thermal.c | 494 ++--- 3 files changed, 351 insertions(+), 160 deletions(-) -- 2.8.1
[PATCH 4/9] thermal/drivers/hisi: add platform prefix to function name
From: Kevin Wangtao reorganize code for follow-up patch, there is no functional change here. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 145 + 1 file changed, 73 insertions(+), 72 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 96904b4..4635839 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -26,25 +26,24 @@ #include "thermal_core.h" -#define TEMP0_LAG (0x0) -#define TEMP0_TH (0x4) -#define TEMP0_RST_TH (0x8) -#define TEMP0_CFG (0xC) -#define TEMP0_CFG_SS_MSK (0xF000) -#define TEMP0_CFG_HDAK_MSK (0x30) -#define TEMP0_EN (0x10) -#define TEMP0_INT_EN (0x14) -#define TEMP0_INT_CLR (0x18) -#define TEMP0_RST_MSK (0x1C) -#define TEMP0_VALUE(0x28) - -#define HISI_TEMP_BASE (-6) -#define HISI_TEMP_RESET(10) -#define HISI_TEMP_STEP (785) -#define HISI_TEMP_LAG (3500) - -#define HISI_MAX_SENSORS 4 -#define HISI_DEFAULT_SENSOR2 +#define HI6220_TEMP0_LAG (0x0) +#define HI6220_TEMP0_TH(0x4) +#define HI6220_TEMP0_RST_TH(0x8) +#define HI6220_TEMP0_CFG (0xC) +#define HI6220_TEMP0_CFG_SS_MSK(0xF000) +#define HI6220_TEMP0_CFG_HDAK_MSK (0x30) +#define HI6220_TEMP0_EN(0x10) +#define HI6220_TEMP0_INT_EN(0x14) +#define HI6220_TEMP0_INT_CLR (0x18) +#define HI6220_TEMP0_RST_MSK (0x1C) +#define HI6220_TEMP0_VALUE (0x28) + +#define HI6220_TEMP_BASE (-6) +#define HI6220_TEMP_RESET (10) +#define HI6220_TEMP_STEP (785) +#define HI6220_TEMP_LAG(3500) + +#define HI6220_DEFAULT_SENSOR 2 struct hisi_thermal_sensor { struct thermal_zone_device *tzd; @@ -78,14 +77,14 @@ struct hisi_thermal_data { * steps = (Temp - TempBase) / 785 * */ -static inline int hisi_thermal_step_to_temp(int step) +static inline int hi6220_thermal_step_to_temp(int step) { - return HISI_TEMP_BASE + (step * HISI_TEMP_STEP); + return HI6220_TEMP_BASE + (step * HI6220_TEMP_STEP); } -static inline int hisi_thermal_temp_to_step(int temp) +static inline int hi6220_thermal_temp_to_step(int temp) { - return DIV_ROUND_UP(temp - HISI_TEMP_BASE, HISI_TEMP_STEP); + return DIV_ROUND_UP(temp - HI6220_TEMP_BASE, HI6220_TEMP_STEP); } /* @@ -112,51 +111,53 @@ static inline int hisi_thermal_temp_to_step(int temp) * * [0:4] : lag register * - * The temperature is coded in steps, cf. HISI_TEMP_STEP. + * The temperature is coded in steps, cf. HI6220_TEMP_STEP. * * Min : 0x00 : 0.0 ??C * Max : 0x1F : 24.3 ??C * * The 'value' parameter is in milliCelsius. */ -static inline void hisi_thermal_set_lag(void __iomem *addr, int value) +static inline void hi6220_thermal_set_lag(void __iomem *addr, int value) { - writel(DIV_ROUND_UP(value, HISI_TEMP_STEP) & 0x1F, addr + TEMP0_LAG); + writel(DIV_ROUND_UP(value, HI6220_TEMP_STEP) & 0x1F, + addr + HI6220_TEMP0_LAG); } -static inline void hisi_thermal_alarm_clear(void __iomem *addr, int value) +static inline void hi6220_thermal_alarm_clear(void __iomem *addr, int value) { - writel(value, addr + TEMP0_INT_CLR); + writel(value, addr + HI6220_TEMP0_INT_CLR); } -static inline void hisi_thermal_alarm_enable(void __iomem *addr, int value) +static inline void hi6220_thermal_alarm_enable(void __iomem *addr, int value) { - writel(value, addr + TEMP0_INT_EN); + writel(value, addr + HI6220_TEMP0_INT_EN); } -static inline void hisi_thermal_alarm_set(void __iomem *addr, int temp) +static inline void hi6220_thermal_alarm_set(void __iomem *addr, int temp) { - writel(hisi_thermal_temp_to_step(temp) | 0x0FF00, addr + TEMP0_TH); + writel(hi6220_thermal_temp_to_step(temp) | 0x0FF00, + addr + HI6220_TEMP0_TH); } -static inline void hisi_thermal_reset_set(void __iomem *addr, int temp) +static inline void hi6220_thermal_reset_set(void __iomem *addr, int temp) { - writel(hisi_thermal_temp_to_step(temp), addr + TEMP0_RST_TH); + writel(hi6220_thermal_temp_to_step(temp), addr + HI6220_TEMP0_RST_TH); } -static inline void hisi_thermal_reset_enable(void __iomem *addr, int value) +static inline void hi6220_thermal_reset_enable(void __iomem *addr, int value) { - writel(value, addr + TEMP0_RST_MSK); + writel(value, addr + HI6220_TEMP0_RST_MSK); } -static inline void
[PATCH 9/9] arm64: dts: register Hi3660's thermal sensor
From: Kevin Wangtao add binding for tsensor on H3660, this tsensor is used for SoC thermal control, it supports alarm interrupt. Signed-off-by: Kevin Wangtao --- arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 8 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi index b7a90d6..ae90991 100644 --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi @@ -978,5 +978,13 @@ clocks = <_ctrl HI3660_OSC32K>; clock-names = "apb_pclk"; }; + + tsensor: tsensor@fff3 { + compatible = "hisilicon,hi3660-tsensor"; + reg = <0x0 0xfff3 0x0 0x1000>; + interrupts = ; + #thermal-sensor-cells = <1>; + }; + }; }; -- 2.8.1
[PATCH 7/9] dt-bindings: Document the hi3660 thermal sensor binding
From: Kevin Wangtao This adds documentation of device tree bindings for the thermal sensor controller of hi3660 SoC. Signed-off-by: Kevin Wangtao --- Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt | 9 + 1 file changed, 9 insertions(+) diff --git a/Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt b/Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt index d48fc52..cef716a 100644 --- a/Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt +++ b/Documentation/devicetree/bindings/thermal/hisilicon-thermal.txt @@ -13,6 +13,7 @@ Example : +for Hi6220: tsensor: tsensor@0,f7030700 { compatible = "hisilicon,tsensor"; reg = <0x0 0xf7030700 0x0 0x1000>; @@ -21,3 +22,11 @@ Example : clock-names = "thermal_clk"; #thermal-sensor-cells = <1>; } + +for Hi3660: + tsensor: tsensor@fff3 { + compatible = "hisilicon,hi3660-tsensor"; + reg = <0x0 0xfff3 0x0 0x1000>; + interrupts = ; + #thermal-sensor-cells = <1>; + }; -- 2.8.1
[PATCH 8/9] thermal/drivers/hisi: add support for hi3660 SoC
From: Kevin Wangtao This patch adds the support for thermal sensor of Hi3660 SoC. Hi3660 tsensor support alarm interrupt and have three configurable alarm thresholds, it also has a configurable hysteresis interval, interrupt will be triggered when temperature rise above the alarm threshold or fall below the hysteresis threshold. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 146 - 1 file changed, 145 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 718376b..133238a 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -39,12 +39,24 @@ #define HI6220_TEMP0_RST_MSK (0x1C) #define HI6220_TEMP0_VALUE (0x28) +#define HI3660_OFFSET(chan)((chan) * 0x40) +#define HI3660_TEMP(chan) (HI3660_OFFSET(chan) + 0x1C) +#define HI3660_TH(chan)(HI3660_OFFSET(chan) + 0x20) +#define HI3660_LAG(chan) (HI3660_OFFSET(chan) + 0x28) +#define HI3660_INT_EN(chan)(HI3660_OFFSET(chan) + 0x2C) +#define HI3660_INT_CLR(chan) (HI3660_OFFSET(chan) + 0x30) + #define HI6220_TEMP_BASE (-6) #define HI6220_TEMP_RESET (10) #define HI6220_TEMP_STEP (785) #define HI6220_TEMP_LAG(3500) +#define HI3660_TEMP_BASE (-63780) +#define HI3660_TEMP_STEP (205) +#define HI3660_TEMP_LAG(4000) + #define HI6220_DEFAULT_SENSOR 2 +#define HI3660_DEFAULT_SENSOR 1 #define MAX_THRES_NUM 2 @@ -96,6 +108,24 @@ static inline int hi6220_thermal_temp_to_step(int temp) } /* + * for Hi3660, + * Step: 189/922 (0.205) + * Temperature base: -63.780??C + * + * The register is programmed in temperature steps, every step is 205 + * millidegree and begins at -63 780 m??C + */ +static inline int hi3660_thermal_step_to_temp(int step) +{ + return HI3660_TEMP_BASE + step * HI3660_TEMP_STEP; +} + +static inline int hi3660_thermal_temp_to_step(int temp) +{ + return DIV_ROUND_UP(temp - HI3660_TEMP_BASE, HI3660_TEMP_STEP); +} + +/* * The lag register contains 5 bits encoding the temperature in steps. * * Each time the temperature crosses the threshold boundary, an @@ -169,6 +199,45 @@ static inline int hi6220_thermal_get_temperature(void __iomem *addr) } /* + * [0:6] lag register + * + * The temperature is coded in steps, cf. HI3660_TEMP_STEP. + * + * Min : 0x00 : 0.0 ??C + * Max : 0x7F : 26.0 ??C + * + */ +static inline void hi3660_thermal_set_lag(void __iomem *addr, + int id, int value) +{ + writel(DIV_ROUND_UP(value, HI3660_TEMP_STEP) & 0x7F, + addr + HI3660_LAG(id)); +} + +static inline void hi3660_thermal_alarm_clear(void __iomem *addr, + int id, int value) +{ + writel(value, addr + HI3660_INT_CLR(id)); +} + +static inline void hi3660_thermal_alarm_enable(void __iomem *addr, + int id, int value) +{ + writel(value, addr + HI3660_INT_EN(id)); +} + +static inline void hi3660_thermal_alarm_set(void __iomem *addr, + int id, int value) +{ + writel(value, addr + HI3660_TH(id)); +} + +static inline int hi3660_thermal_get_temperature(void __iomem *addr, int id) +{ + return hi3660_thermal_step_to_temp(readl(addr + HI3660_TEMP(id))); +} + +/* * Temperature configuration register - Sensor selection * * Bits [19:12] @@ -206,11 +275,22 @@ static int hi6220_thermal_irq_handler(struct hisi_thermal_data *data) return 0; } +static int hi3660_thermal_irq_handler(struct hisi_thermal_data *data) +{ + hi3660_thermal_alarm_clear(data->regs, data->sensor.id, 1); + return 0; +} + static int hi6220_thermal_get_temp(struct hisi_thermal_data *data) { return hi6220_thermal_get_temperature(data->regs); } +static int hi3660_thermal_get_temp(struct hisi_thermal_data *data) +{ + return hi3660_thermal_get_temperature(data->regs, data->sensor.id); +} + static int hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) { /* disable sensor module */ @@ -222,6 +302,13 @@ static int hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) return 0; } +static int hi3660_thermal_disable_sensor(struct hisi_thermal_data *data) +{ + /* disable sensor module */ + hi3660_thermal_alarm_enable(data->regs, data->sensor.id, 0); + return 0; +} + static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) { struct hisi_thermal_sensor *sensor = >sensor; @@ -260,6 +347,29 @@ static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) return 0; } +static int
[PATCH 5/9] thermal/drivers/hisi: perpare to add support for other hisi platform
From: Kevin Wangtao For platform compatibility, add tsensor operation function pointer to thermal data, and each platform has its own probe function to register proper tsensor operation function to the pointer, platform related resource request are also implemented in the platform probe function. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 135 +++-- 1 file changed, 89 insertions(+), 46 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 4635839..f9d9fd6 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "thermal_core.h" @@ -30,7 +31,7 @@ #define HI6220_TEMP0_TH(0x4) #define HI6220_TEMP0_RST_TH(0x8) #define HI6220_TEMP0_CFG (0xC) -#define HI6220_TEMP0_CFG_SS_MSK(0xF000) +#define HI6220_TEMP0_CFG_SS_MSK(0xF000) #define HI6220_TEMP0_CFG_HDAK_MSK (0x30) #define HI6220_TEMP0_EN(0x10) #define HI6220_TEMP0_INT_EN(0x14) @@ -41,7 +42,7 @@ #define HI6220_TEMP_BASE (-6) #define HI6220_TEMP_RESET (10) #define HI6220_TEMP_STEP (785) -#define HI6220_TEMP_LAG(3500) +#define HI6220_TEMP_LAG(3500) #define HI6220_DEFAULT_SENSOR 2 @@ -52,6 +53,10 @@ struct hisi_thermal_sensor { }; struct hisi_thermal_data { + int (*get_temp)(struct hisi_thermal_data *data); + int (*enable_sensor)(struct hisi_thermal_data *data); + int (*disable_sensor)(struct hisi_thermal_data *data); + int (*irq_handler)(struct hisi_thermal_data *data); struct platform_device *pdev; struct clk *clk; struct hisi_thermal_sensor sensor; @@ -59,6 +64,7 @@ struct hisi_thermal_data { int irq; }; + /* * The temperature computation on the tsensor is as follow: * Unit: millidegree Celsius @@ -192,7 +198,18 @@ static inline void hi6220_thermal_hdak_set(void __iomem *addr, int value) (value << 4), addr + HI6220_TEMP0_CFG); } -static void hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) +static int hi6220_thermal_irq_handler(struct hisi_thermal_data *data) +{ + hi6220_thermal_alarm_clear(data->regs, 1); + return 0; +} + +static int hi6220_thermal_get_temp(struct hisi_thermal_data *data) +{ + return hi6220_thermal_get_temperature(data->regs); +} + +static int hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) { /* disable sensor module */ hi6220_thermal_enable(data->regs, 0); @@ -200,9 +217,9 @@ static void hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) hi6220_thermal_reset_enable(data->regs, 0); clk_disable_unprepare(data->clk); + return 0; } - static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) { struct hisi_thermal_sensor *sensor = >sensor; @@ -240,12 +257,50 @@ static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) return 0; } + +static int hi6220_thermal_probe(struct hisi_thermal_data *data) +{ + struct platform_device *pdev = data->pdev; + struct device *dev = >dev; + struct resource *res; + int ret; + + data->get_temp = hi6220_thermal_get_temp; + data->enable_sensor = hi6220_thermal_enable_sensor; + data->disable_sensor = hi6220_thermal_disable_sensor; + data->irq_handler = hi6220_thermal_irq_handler; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(data->regs)) { + dev_err(dev, "failed to get io address\n"); + return PTR_ERR(data->regs); + } + + data->clk = devm_clk_get(dev, "thermal_clk"); + if (IS_ERR(data->clk)) { + ret = PTR_ERR(data->clk); + if (ret != -EPROBE_DEFER) + dev_err(dev, "failed to get thermal clk: %d\n", ret); + return ret; + } + + data->irq = platform_get_irq(pdev, 0); + if (data->irq < 0) + return data->irq; + + data->sensor.id = HI6220_DEFAULT_SENSOR; + + return 0; +} + + static int hisi_thermal_get_temp(void *__data, int *temp) { struct hisi_thermal_data *data = __data; struct hisi_thermal_sensor *sensor = >sensor; - *temp = hi6220_thermal_get_temperature(data->regs); + *temp = data->get_temp(data); dev_dbg(>pdev->dev, "id=%d, temp=%d, thres=%d\n", sensor->id, *temp, sensor->thres_temp); @@ -263,7 +318,7 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) struct hisi_thermal_sensor
[PATCH 1/9] thermal/drivers/hisi: move clk operation to related function
From: Kevin Wangtao The sensor's clock is enabled and disabled outside of the probe and disable function. Moving the corresponding action in the hisi_thermal_setup() and hisi_thermal_disable_sensor(), factors out some lines of code and makes the code more symmetric. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 29 + 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 39f4627..c43e3df 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -203,6 +203,8 @@ static void hisi_thermal_disable_sensor(struct hisi_thermal_data *data) hisi_thermal_enable(data->regs, 0); hisi_thermal_alarm_enable(data->regs, 0); hisi_thermal_reset_enable(data->regs, 0); + + clk_disable_unprepare(data->clk); } static int hisi_thermal_get_temp(void *__data, int *temp) @@ -297,9 +299,13 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, static int hisi_thermal_setup(struct hisi_thermal_data *data) { - struct hisi_thermal_sensor *sensor; + struct hisi_thermal_sensor *sensor = >sensor; + int ret; - sensor = >sensor; + /* enable clock for tsensor */ + ret = clk_prepare_enable(data->clk); + if (ret) + return ret; /* disable module firstly */ hisi_thermal_reset_enable(data->regs, 0); @@ -363,13 +369,6 @@ static int hisi_thermal_probe(struct platform_device *pdev) return ret; } - /* enable clock for thermal */ - ret = clk_prepare_enable(data->clk); - if (ret) { - dev_err(>dev, "failed to enable thermal clk: %d\n", ret); - return ret; - } - ret = hisi_thermal_register_sensor(pdev, data, >sensor, HISI_DEFAULT_SENSOR); @@ -405,7 +404,6 @@ static int hisi_thermal_remove(struct platform_device *pdev) hisi_thermal_toggle_sensor(sensor, false); hisi_thermal_disable_sensor(data); - clk_disable_unprepare(data->clk); return 0; } @@ -417,23 +415,14 @@ static int hisi_thermal_suspend(struct device *dev) hisi_thermal_disable_sensor(data); - clk_disable_unprepare(data->clk); - return 0; } static int hisi_thermal_resume(struct device *dev) { struct hisi_thermal_data *data = dev_get_drvdata(dev); - int ret; - ret = clk_prepare_enable(data->clk); - if (ret) - return ret; - - hisi_thermal_setup(data); - - return 0; + return hisi_thermal_setup(data); } #endif -- 2.8.1
[PATCH 3/9] thermal/drivers/hisi: put platform code together
From: Kevin Wangtao reorganize code for follow-up patch, there is no functional change here. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 76 +- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index c8b651d..96904b4 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -201,6 +201,44 @@ static void hisi_thermal_disable_sensor(struct hisi_thermal_data *data) clk_disable_unprepare(data->clk); } + +static int hisi_thermal_setup(struct hisi_thermal_data *data) +{ + struct hisi_thermal_sensor *sensor = >sensor; + int ret; + + /* enable clock for tsensor */ + ret = clk_prepare_enable(data->clk); + if (ret) + return ret; + + /* disable module firstly */ + hisi_thermal_reset_enable(data->regs, 0); + hisi_thermal_enable(data->regs, 0); + + /* select sensor id */ + hisi_thermal_sensor_select(data->regs, sensor->id); + + /* setting the hdak time */ + hisi_thermal_hdak_set(data->regs, 0); + + /* setting lag value between current temp and the threshold */ + hisi_thermal_set_lag(data->regs, HISI_TEMP_LAG); + + /* enable for interrupt */ + hisi_thermal_alarm_set(data->regs, sensor->thres_temp); + + hisi_thermal_reset_set(data->regs, HISI_TEMP_RESET); + + /* enable module */ + hisi_thermal_reset_enable(data->regs, 1); + hisi_thermal_enable(data->regs, 1); + + hisi_thermal_alarm_clear(data->regs, 0); + hisi_thermal_alarm_enable(data->regs, 1); + + return 0; +} static int hisi_thermal_get_temp(void *__data, int *temp) { struct hisi_thermal_data *data = __data; @@ -291,44 +329,6 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED); } -static int hisi_thermal_setup(struct hisi_thermal_data *data) -{ - struct hisi_thermal_sensor *sensor = >sensor; - int ret; - - /* enable clock for tsensor */ - ret = clk_prepare_enable(data->clk); - if (ret) - return ret; - - /* disable module firstly */ - hisi_thermal_reset_enable(data->regs, 0); - hisi_thermal_enable(data->regs, 0); - - /* select sensor id */ - hisi_thermal_sensor_select(data->regs, sensor->id); - - /* setting the hdak time */ - hisi_thermal_hdak_set(data->regs, 0); - - /* setting lag value between current temp and the threshold */ - hisi_thermal_set_lag(data->regs, HISI_TEMP_LAG); - - /* enable for interrupt */ - hisi_thermal_alarm_set(data->regs, sensor->thres_temp); - - hisi_thermal_reset_set(data->regs, HISI_TEMP_RESET); - - /* enable module */ - hisi_thermal_reset_enable(data->regs, 1); - hisi_thermal_enable(data->regs, 1); - - hisi_thermal_alarm_clear(data->regs, 0); - hisi_thermal_alarm_enable(data->regs, 1); - - return 0; -} - static int hisi_thermal_probe(struct platform_device *pdev) { struct hisi_thermal_data *data; -- 2.8.1
[PATCH 2/9] thermal/drivers/hisi: use round up step value
From: Kevin Wangtao Use round up divide to ensure the programmed value of threshold and lag not less than we set, and in order to keep the accuracy while using round up divide, the step value should also be a round up value. Then there is no need to use hisi_thermal_round_temp. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 22 -- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index c43e3df..c8b651d 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -40,7 +40,7 @@ #define HISI_TEMP_BASE (-6) #define HISI_TEMP_RESET(10) -#define HISI_TEMP_STEP (784) +#define HISI_TEMP_STEP (785) #define HISI_TEMP_LAG (3500) #define HISI_MAX_SENSORS 4 @@ -63,19 +63,19 @@ struct hisi_thermal_data { /* * The temperature computation on the tsensor is as follow: * Unit: millidegree Celsius - * Step: 255/200 (0.7843) + * Step: 200/255 (0.7843) * Temperature base: -60??C * - * The register is programmed in temperature steps, every step is 784 + * The register is programmed in temperature steps, every step is 785 * millidegree and begins at -60 000 m??C * * The temperature from the steps: * - * Temp = TempBase + (steps x 784) + * Temp = TempBase + (steps x 785) * * and the steps from the temperature: * - * steps = (Temp - TempBase) / 784 + * steps = (Temp - TempBase) / 785 * */ static inline int hisi_thermal_step_to_temp(int step) @@ -85,13 +85,7 @@ static inline int hisi_thermal_step_to_temp(int step) static inline int hisi_thermal_temp_to_step(int temp) { - return (temp - HISI_TEMP_BASE) / HISI_TEMP_STEP; -} - -static inline int hisi_thermal_round_temp(int temp) -{ - return hisi_thermal_step_to_temp( - hisi_thermal_temp_to_step(temp)); + return DIV_ROUND_UP(temp - HISI_TEMP_BASE, HISI_TEMP_STEP); } /* @@ -127,7 +121,7 @@ static inline int hisi_thermal_round_temp(int temp) */ static inline void hisi_thermal_set_lag(void __iomem *addr, int value) { - writel((value / HISI_TEMP_STEP) & 0x1F, addr + TEMP0_LAG); + writel(DIV_ROUND_UP(value, HISI_TEMP_STEP) & 0x1F, addr + TEMP0_LAG); } static inline void hisi_thermal_alarm_clear(void __iomem *addr, int value) @@ -274,7 +268,7 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, for (i = 0; i < of_thermal_get_ntrips(sensor->tzd); i++) { if (trip[i].type == THERMAL_TRIP_PASSIVE) { - sensor->thres_temp = hisi_thermal_round_temp(trip[i].temperature); + sensor->thres_temp = trip[i].temperature; break; } } -- 2.8.1
[PATCH 6/9] thermal/drivers/hisi: add support for multi temp threshold
From: Kevin Wangtao tsensor may have multi alarm levels, so we can support more trip point interrupt. Signed-off-by: Kevin Wangtao --- drivers/thermal/hisi_thermal.c | 21 - 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index f9d9fd6..718376b 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -46,10 +46,12 @@ #define HI6220_DEFAULT_SENSOR 2 +#define MAX_THRES_NUM 2 + struct hisi_thermal_sensor { struct thermal_zone_device *tzd; uint32_t id; - uint32_t thres_temp; + uint32_t thres_temp[MAX_THRES_NUM]; }; struct hisi_thermal_data { @@ -244,7 +246,7 @@ static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) hi6220_thermal_set_lag(data->regs, HI6220_TEMP_LAG); /* enable for interrupt */ - hi6220_thermal_alarm_set(data->regs, sensor->thres_temp); + hi6220_thermal_alarm_set(data->regs, sensor->thres_temp[0]); hi6220_thermal_reset_set(data->regs, HI6220_TEMP_RESET); @@ -303,7 +305,7 @@ static int hisi_thermal_get_temp(void *__data, int *temp) *temp = data->get_temp(data); dev_dbg(>pdev->dev, "id=%d, temp=%d, thres=%d\n", - sensor->id, *temp, sensor->thres_temp); + sensor->id, *temp, sensor->thres_temp[0]); return 0; } @@ -322,16 +324,16 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) hisi_thermal_get_temp(data, ); - if (temp >= sensor->thres_temp) { + if (temp >= sensor->thres_temp[0]) { dev_crit(>pdev->dev, "THERMAL ALARM: %d > %d\n", -temp, sensor->thres_temp); +temp, sensor->thres_temp[0]); thermal_zone_device_update(data->sensor.tzd, THERMAL_EVENT_UNSPECIFIED); } else { dev_crit(>pdev->dev, "THERMAL ALARM stopped: %d < %d\n", -temp, sensor->thres_temp); +temp, sensor->thres_temp[0]); } return IRQ_HANDLED; @@ -341,7 +343,7 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, struct hisi_thermal_data *data, struct hisi_thermal_sensor *sensor) { - int ret, i; + int ret, i, thres_idx = 0; const struct thermal_trip *trip; sensor->tzd = devm_thermal_zone_of_sensor_register(>dev, @@ -359,8 +361,9 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, for (i = 0; i < of_thermal_get_ntrips(sensor->tzd); i++) { if (trip[i].type == THERMAL_TRIP_PASSIVE) { - sensor->thres_temp = trip[i].temperature; - break; + sensor->thres_temp[thres_idx++] = trip[i].temperature; + if (thres_idx >= MAX_THRES_NUM) + break; } } -- 2.8.1
[PATCH v4 3/3] arm64: dts: register Hi3660's thermal sensor
From: Tao Wang Bind thermal sensor driver for Hi3660. Signed-off-by: Tao Wang Signed-off-by: Leo Yan --- 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 #include +#include / { compatible = "hisilicon,hi3660"; @@ -848,5 +849,18 @@ _cfg_func>; status = "disabled"; }; + + tsensor: tsensor@fff3 { + 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,coef = <165000 (-4)>; + 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 000..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_TEMP0 +#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
[PATCH v4 0/3] thermal: add thermal sensor driver for Hi3660
From: Tao Wang 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
[PATCH v4 2/3] thermal: hisilicon: add thermal sensor driver for Hi3660
From: Tao Wang 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 Signed-off-by: Leo Yan --- 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 000..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 + * Author: Leo Yan + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "thermal_core.h" + +#define VIRTUAL_SENSORS2 + +/* 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
[PATCH v4 1/3] dt-bindings: Document the hi3660 thermal sensor bindings
From: Tao Wang This adds documentation of device tree bindings for the thermal sensor controller of hi3660 SoC. Signed-off-by: Tao Wang --- .../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 000..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@fff3 { + 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,coef = <165000 (-4)>; + hisi,adc-range = <0x74 0x39A>; + #thermal-sensor-cells = <1>; +}; -- 2.8.1
[PATCH v3 0/3] thermal: add thermal sensor driver for Hi3660
From: Tao Wang 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
[PATCH v3 3/3] arm64: dts: register Hi3660's thermal sensor
From: Tao Wang Bind thermal sensor driver for Hi3660. Signed-off-by: Tao Wang Signed-off-by: Leo Yan --- 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 #include +#include / { compatible = "hisilicon,hi3660"; @@ -848,5 +849,14 @@ _cfg_func>; status = "disabled"; }; + + tsensor: tsensor@FFF3000 { + compatible = "hisilicon,tsensor"; + reg = <0x0 0xfff3 0x0 0x1000>; + offset = <0x1c 0x5c 0x9c>; + coefficients = <165000 (-4)>; + 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 000..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_TEMP0 +#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
[PATCH v3 1/3] dt-bindings: Document the hi3660 thermal sensor bindings
From: Tao Wang This adds documentation of device tree bindings for the thermal sensor controller of hi3660 SoC. Signed-off-by: Tao Wang --- .../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 000..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 0xfff3 0x0 0x1000>; + offset = <0x1c 0x5c 0x9c>; + coefficients = <165000 (-4)>; + hisi,adc-range = <0x74 0x39A>; + #thermal-sensor-cells = <1>; +}; -- 2.8.1
[PATCH v3 2/3] thermal: hisilicon: add thermal sensor driver for Hi3660
From: Tao Wang 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 Signed-off-by: Leo Yan --- 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 000..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 + * Author: Leo Yan + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "thermal_core.h" + +#define VIRTUAL_SENSORS2 + +/* 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->coe
[PATCH] cpufreq: dt: Add support for hi3660
Add the compatible string for supporting the generic device tree cpufreq-dt driver on Hisilicon's 3660 SoC. Signed-off-by: Tao Wang --- drivers/cpufreq/cpufreq-dt-platdev.c |1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 921b4a6..b54e610 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -32,6 +32,7 @@ { .compatible = "arm,integrator-cp", }, { .compatible = "hisilicon,hi6220", }, + { .compatible = "hisilicon,hi3660", }, { .compatible = "fsl,imx27", }, { .compatible = "fsl,imx51", }, -- 1.7.9.5
[Patch v2] cpufreq: dt: Add support for hi3660
Add the compatible string for supporting the generic device tree cpufreq-dt driver on Hisilicon's 3660 SoC. Signed-off-by: Tao Wang --- Changes in v2: - changed order according to Viresh's suggestion drivers/cpufreq/cpufreq-dt-platdev.c |1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index 921b4a6..1c26292 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -31,6 +31,7 @@ { .compatible = "arm,integrator-ap", }, { .compatible = "arm,integrator-cp", }, + { .compatible = "hisilicon,hi3660", }, { .compatible = "hisilicon,hi6220", }, { .compatible = "fsl,imx27", }, -- 1.7.9.5
[PATCH 1/3] dt-bindings: Document the hi3660 thermal sensor bindings
This adds documentation of device tree bindings for the thermal sensor controller of hi3660 SoC. Signed-off-by: Tao Wang --- .../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 000..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 0xfff3 0x0 0x1000>; + #thermal-sensor-cells = <1>; + status = "ok"; +}; -- 1.7.9.5
[PATCH 3/3] arm64: dts: register Hi3660's thermal sensor
Bind thermal sensor driver for Hi3660. Signed-off-by: Tao Wang Signed-off-by: Leo Yan --- 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 0xfff3 0x0 0x1000>; + #thermal-sensor-cells = <1>; + status = "ok"; + }; }; }; -- 1.7.9.5
[PATCH 2/3] thermal: hisilicon: add thermal sensor driver for Hi3660
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 Signed-off-by: Leo Yan --- 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 000..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 + * Author: Leo Yan + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "thermal_core.h" + +#define HW_MAX_SENSORS 4 +#define HISI_MAX_SENSORS 6 +#define SENSOR_MAX 4 +#define SENSOR_AVG 5 + +#define ADC_MIN116 +#define ADC_MAX922 + +/* 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) - 4; + + return 0; +} + +static struct thermal_zone_of_device_ops hi3660_of_thermal_ops = { + .get_temp = hi3660_thermal_get_temp, +}; + +static int hi3660_thermal_register_senso
[Patch v2 1/3] dt-bindings: Document the hi3660 thermal sensor bindings
This adds documentation of device tree bindings for the thermal sensor controller of hi3660 SoC. Signed-off-by: Tao Wang --- 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 000..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 0xfff3 0x0 0x1000>; + #thermal-sensor-cells = <1>; +}; -- 1.7.9.5
[Patch v2 2/3] thermal: hisilicon: add thermal sensor driver for Hi3660
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 Signed-off-by: Leo Yan --- 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 000..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 + * Author: Leo Yan + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "thermal_core.h" + +#define HW_MAX_SENSORS 4 +#define HISI_MAX_SENSORS 6 +#define SENSOR_MAX 4 +#define SENSOR_AVG 5 + +#define ADC_MIN116 +#define ADC_MAX922 + +/* 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) - 4; + + return 0; +} + +static struct thermal_zone_of_device_ops hi3660_of_thermal_ops = { + .get_temp = hi3660_thermal_get_temp, +}; + +stat
[Patch v2 3/3] arm64: dts: register Hi3660's thermal sensor
Bind thermal sensor driver for Hi3660. Signed-off-by: Tao Wang Signed-off-by: Leo Yan --- 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 @@ _cfg_func>; status = "disabled"; }; + + tsensor: tsensor { + compatible = "hisilicon,hi3660-thermal"; + reg = <0x0 0xfff3 0x0 0x1000>; + #thermal-sensor-cells = <1>; + }; }; }; -- 1.7.9.5
[PATCH RFC 2/2] thermal/cpu idle cooling: cpu idle cooling cooperate with cpu cooling
This implements precise cpu thermal control through the cooperation between cpu idle cooling and cpu cooling, avoid frequency decrease if idle injection can achieve the target power limit. This can bring a smoother temperature curve and performance improvement in some case when there are big power gaps between cpu OPPs. Signed-off-by: Tao Wang --- drivers/thermal/Kconfig| 17 drivers/thermal/cpu_cooling.c | 31 + drivers/thermal/cpu_idle_cooling.c |5 + include/linux/cpu_idle_cooling.h | 38 4 files changed, 91 insertions(+) create mode 100644 include/linux/cpu_idle_cooling.h diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index f78e85c..ef43d15 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -167,6 +167,23 @@ config CPU_IDLE_THERMAL If you want this support, you should say Y here. +config CPU_THERMAL_COMBO + bool "precise cpu cooling support" + depends on CPU_THERMAL + depends on CPU_IDLE_THERMAL + help + This implements precise cpu thermal control through the cooperation + between idle cooling and cpu cooling. + + This will prevent cpu cooling scaling down cpu frequency when idle + injection can meet the power budget. + + This can bring a smoother temperature curve and performance + improvement in some case when there are big power gaps between cpu + OPPs. + + If you want this support, you should say Y here. + config CLOCK_THERMAL bool "Generic clock cooling support" depends on COMMON_CLK diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c index 69d0f43..a81cd92 100644 --- a/drivers/thermal/cpu_cooling.c +++ b/drivers/thermal/cpu_cooling.c @@ -31,6 +31,7 @@ #include #include #include +#include #include @@ -649,6 +650,31 @@ static int cpufreq_state2power(struct thermal_cooling_device *cdev, return ret; } +#ifdef CONFIG_CPU_THERMAL_COMBO +static void idle_cooling_freq_adjust( + struct cpufreq_cooling_device *cpufreq_device, + u32 power, unsigned int *target_freq) +{ + unsigned long target_load, max_idle_ratio; + unsigned int idle_freq; + s32 cur_dyn_power; + + max_idle_ratio = get_max_idle_state(_device->allowed_cpus); + cur_dyn_power = power * 100 / (100 - max_idle_ratio); + idle_freq = cpu_power_to_freq(cpufreq_device, cur_dyn_power); + + cur_dyn_power = cpu_freq_to_power(cpufreq_device, idle_freq); + target_load = (power * 100) / cur_dyn_power; + if (target_load < 100 + && ((idle_freq * target_load) >= ((*target_freq) * 100))) { + *target_freq = idle_freq; + } else { + target_load = 100; + } + set_idle_state(_device->allowed_cpus, 100 - target_load); +} +#endif + /** * cpufreq_power2state() - convert power to a cooling device state * @cdev: _cooling_device pointer @@ -696,6 +722,11 @@ static int cpufreq_power2state(struct thermal_cooling_device *cdev, normalised_power = (dyn_power * 100) / last_load; target_freq = cpu_power_to_freq(cpufreq_device, normalised_power); +#ifdef CONFIG_CPU_THERMAL_COMBO + idle_cooling_freq_adjust(cpufreq_device, + normalised_power, _freq); +#endif + *state = cpufreq_cooling_get_level(cpu, target_freq); if (*state == THERMAL_CSTATE_INVALID) { dev_err_ratelimited(>device, diff --git a/drivers/thermal/cpu_idle_cooling.c b/drivers/thermal/cpu_idle_cooling.c index 89a15c5..4a1844d 100644 --- a/drivers/thermal/cpu_idle_cooling.c +++ b/drivers/thermal/cpu_idle_cooling.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +36,11 @@ #include #include +#ifdef CONFIG_CPU_THERMAL_COMBO +#define MAX_TARGET_RATIO (20U) +#else #define MAX_TARGET_RATIO (50U) +#endif #define DEFAULT_WINDOW_SIZE(1) #define DEFAULT_DURATION_JIFFIES (20) diff --git a/include/linux/cpu_idle_cooling.h b/include/linux/cpu_idle_cooling.h new file mode 100644 index 000..da5f19a --- /dev/null +++ b/include/linux/cpu_idle_cooling.h @@ -0,0 +1,38 @@ +/* + * linux/drivers/thermal/cpu_idle_cooling.h + * + * Copyright (C) 2017 Tao Wang + * + * 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 detail
[PATCH RFC 1/2] thermal/cpu idle cooling: Introduce cpu idle cooling driver
cpu idle cooling driver performs synchronized idle injection across all cpu in same cluster, offers a new method to cooling down cpu, that is similar to intel_power_clamp driver, but is basically designed for ARM platform. Each cluster has its own idle cooling device, each core has its own idle injection thread, idle injection thread use play_idle to enter idle. In order to reach deepest idle state, all cores are aligned by jiffies. the injected idle ratio can be controlled through cooling device interface. Signed-off-by: Tao Wang --- drivers/thermal/Kconfig| 13 + drivers/thermal/Makefile |3 + drivers/thermal/cpu_idle_cooling.c | 648 3 files changed, 664 insertions(+) create mode 100644 drivers/thermal/cpu_idle_cooling.c diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index b5b5fac..f78e85c 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -154,6 +154,19 @@ config CPU_THERMAL If you want this support, you should say Y here. +config CPU_IDLE_THERMAL + tristate "generic cpu idle cooling support" + depends on CPU_FREQ + help + This implements the generic cpu cooling mechanism through idle + injection. + + This will throttle cpu by injecting specified idle time in + a fixed cycle. All cpu in same cluster will enter idle synchronously + to reach deepest idle state when injecting idle. + + If you want this support, you should say Y here. + config CLOCK_THERMAL bool "Generic clock cooling support" depends on COMMON_CLK diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 094d703..a4db66e 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -26,6 +26,9 @@ thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o # devfreq cooling thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o +# cpu idle cooling +obj-$(CONFIG_CPU_IDLE_THERMAL) += cpu_idle_cooling.o + # platform thermal drivers obj-y += broadcom/ obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o diff --git a/drivers/thermal/cpu_idle_cooling.c b/drivers/thermal/cpu_idle_cooling.c new file mode 100644 index 000..89a15c5 --- /dev/null +++ b/drivers/thermal/cpu_idle_cooling.c @@ -0,0 +1,648 @@ +/* + * linux/drivers/thermal/cpu_idle_cooling.c + * + * Copyright (C) 2017 Tao Wang + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_TARGET_RATIO (50U) + +#define DEFAULT_WINDOW_SIZE(1) +#define DEFAULT_DURATION_JIFFIES (20) + +struct cpu_idle_cooling_device { + int id; + struct thermal_cooling_device *cooling_dev; + wait_queue_head_t wait_queue; + + /* The cpu assigned to collect stat and update +* control parameters. default to BSP but BSP +* can be offlined. +*/ + unsigned long control_cpu; + + unsigned int set_target_ratio; + unsigned int current_ratio; + unsigned int control_ratio; + unsigned int duration; + unsigned int window_size; + + cpumask_var_t related_cpus; + cpumask_var_t injected_cpus; + struct list_head node; + bool should_skip; + bool clamping; +}; + +static LIST_HEAD(cpu_idle_cooling_dev_list); +static DEFINE_PER_CPU(struct task_struct *, idle_injection_thread_ptr); +static DEFINE_MUTEX(cpu_idle_cooling_lock); + +unsigned long idle_time[NR_CPUS] = {0}; +unsigned long time_stamp[NR_CPUS] = {0}; +static enum cpuhp_state hp_state; + +#define STORE_PARAM(param, min, max) \ +static ssize_t store_##param(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + unsigned int new_value; \ + struct thermal_cooling_device *cdev;\ + struct cpu_idle_cooling_device *idle_cooling_dev; \ +