[PATCH v3 0/3] thermal: add thermal sensor driver for Hi3660

2017-08-10 Thread Tao Wang
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

2017-08-10 Thread Tao Wang
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

2017-08-10 Thread Tao Wang
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

2017-08-10 Thread Tao Wang
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

2017-06-19 Thread Tao Wang
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

2017-06-19 Thread 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 <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

2017-06-19 Thread Tao Wang
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

2017-06-21 Thread Tao Wang
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

2017-06-21 Thread Tao Wang
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

2017-06-21 Thread 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 <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

2017-05-23 Thread Tao Wang
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

2017-05-23 Thread Tao Wang
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

2017-06-05 Thread Tao Wang
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

2017-06-05 Thread Tao Wang
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

2017-09-22 Thread Tao Wang
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 2/9] thermal/drivers/hisi: use round up step value

2017-09-22 Thread Tao Wang
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 8/9] thermal/drivers/hisi: add support for hi3660 SoC

2017-09-22 Thread Tao Wang
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 

[PATCH 5/9] thermal/drivers/hisi: perpare to add support for other hisi platform

2017-09-22 Thread Tao Wang
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, 

[PATCH 1/9] thermal/drivers/hisi: move clk operation to related function

2017-09-22 Thread Tao Wang
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 7/9] dt-bindings: Document the hi3660 thermal sensor binding

2017-09-22 Thread Tao Wang
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 3/9] thermal/drivers/hisi: put platform code together

2017-09-22 Thread Tao Wang
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 9/9] arm64: dts: register Hi3660's thermal sensor

2017-09-22 Thread Tao Wang
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 4/9] thermal/drivers/hisi: add platform prefix to function name

2017-09-22 Thread Tao Wang
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 + 

[PATCH 0/9] add support for Hi3660 tsensor

2017-09-22 Thread Tao Wang
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 v4 0/3] thermal: add thermal sensor driver for Hi3660

2017-08-29 Thread Tao Wang
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

2017-08-29 Thread Tao Wang
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

2017-08-29 Thread Tao Wang
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

2017-08-29 Thread Tao Wang
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

2017-10-18 Thread Tao Wang
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] thermal/drivers/hisi: disable multi alarm support for hi3660 SoC

2017-10-18 Thread Tao Wang
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

2017-09-22 Thread Tao Wang
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

2017-09-22 Thread Tao Wang
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

2017-09-22 Thread Tao Wang
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

2017-09-22 Thread Tao Wang
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

2017-09-22 Thread Tao Wang
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

2017-09-22 Thread Tao Wang
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

2017-09-22 Thread Tao Wang
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

2017-09-22 Thread Tao Wang
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

2017-09-22 Thread Tao Wang
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

2017-09-22 Thread Tao Wang
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

2017-08-29 Thread Tao Wang
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

2017-08-29 Thread Tao Wang
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

2017-08-29 Thread Tao Wang
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

2017-08-29 Thread Tao Wang
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

2017-08-10 Thread Tao Wang
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

2017-08-10 Thread Tao Wang
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

2017-08-10 Thread Tao Wang
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

2017-08-10 Thread Tao Wang
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

2017-05-23 Thread Tao Wang
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

2017-05-23 Thread Tao Wang
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

2017-06-19 Thread 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/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

2017-06-19 Thread 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 |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

2017-06-19 Thread 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  |   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

2017-06-21 Thread Tao Wang
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

2017-06-21 Thread 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 
---
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

2017-06-21 Thread Tao Wang
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

2017-06-05 Thread Tao Wang
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

2017-06-05 Thread Tao Wang
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;   \
+