aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-17 13:16:27 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-17 13:16:27 -0500
commit2efda9042d76fcab0fb87b7ee8d84da52bf122b0 (patch)
treef390199ae330fbe20b3c9d8fe1021d909f752421
parent0b4954c46943e8f15b9379eed4f133c874a0bc66 (diff)
parent2707dbd09a859b7205917f9baf9d0192944ac46c (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal management update from Zhang Rui: "Summary: - of-thermal extension to allow drivers to register and use its functionality in a better way, without exploiting thermal core. From Lukasz Majewski. - Fix a bug in intel_soc_dts_thermal driver which calls a sleep function in interrupt handler. From Maurice Petallo. - add a thermal UAPI header file for exporting the thermal generic netlink information to user-space. From Florian Fainelli. - First round of refactoring in Exynos driver. Bartlomiej and Lukasz are attempting to make it lean and easier to understand. - New thermal driver for Rockchip (rk3288), with support for DT thermal. From Caesar Wang. - New thermal driver for Nvidia, Tegra124 SOCTHERM driver, with support for DT thermal. From Mikko Perttunen. - New cooling device, based on common clock framework. From Eduardo Valentin. - a couple of small fixes in thermal core framework. From Srinivas Pandruvada, Javi Merino, Luis Henriques. - Dropping Armada A375-Z1 SoC thermal support as the chip is not in the market, armada folks decided to drop its support. - a couple of small fixes and cleanups in int340x thermal driver" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (58 commits) thermal: provide an UAPI header file Thermal/int340x: Clear the error value of the last acpi_bus_get_device() call thermal/powerclamp: add id for braswell cpu thermal: Intel SoC DTS: Don't do thermal zone update inside spin_lock Thermal: fix platform_no_drv_owner.cocci warnings Thermal/int340x: avoid unnecessary pointer casting thermal: int3403: Delete a check before thermal_zone_device_unregister() thermal/int3400: export uuids thermal: of: Extend current of-thermal.c code to allow setting emulated temp thermal: of: Extend of-thermal to export table of trip points thermal: of: Rename struct __thermal_trip to struct thermal_trip thermal: of: Extend of-thermal.c to provide check if trip point is valid thermal: of: Extend of-thermal.c to provide number of trip points thermal: Fix error path in thermal_init() thermal: lock the thermal zone when switching governors thermal: core: ignore invalid trip temperature thermal: armada: Remove support for A375-Z1 SoC thermal: rockchip: add driver for thermal dt-bindings: document Rockchip thermal thermal: exynos: remove exynos_tmu_data.h include ...
-rw-r--r--Documentation/devicetree/bindings/thermal/armada-thermal.txt8
-rw-r--r--Documentation/devicetree/bindings/thermal/rockchip-thermal.txt68
-rw-r--r--Documentation/devicetree/bindings/thermal/tegra-soctherm.txt53
-rw-r--r--MAINTAINERS1
-rw-r--r--arch/arm/boot/dts/tegra124-jetson-tk1.dts44
-rw-r--r--arch/arm/boot/dts/tegra124.dtsi47
-rw-r--r--drivers/hwmon/lm75.c9
-rw-r--r--drivers/hwmon/ntc_thermistor.c6
-rw-r--r--drivers/hwmon/tmp102.c6
-rw-r--r--drivers/thermal/Kconfig32
-rw-r--r--drivers/thermal/Makefile5
-rw-r--r--drivers/thermal/armada_thermal.c20
-rw-r--r--drivers/thermal/clock_cooling.c485
-rw-r--r--drivers/thermal/int340x_thermal/acpi_thermal_rel.c12
-rw-r--r--drivers/thermal/int340x_thermal/int3400_thermal.c80
-rw-r--r--drivers/thermal/int340x_thermal/int3403_thermal.c4
-rw-r--r--drivers/thermal/intel_powerclamp.c1
-rw-r--r--drivers/thermal/intel_soc_dts_thermal.c12
-rw-r--r--drivers/thermal/of-thermal.c148
-rw-r--r--drivers/thermal/rockchip_thermal.c693
-rw-r--r--drivers/thermal/samsung/exynos_thermal_common.h1
-rw-r--r--drivers/thermal/samsung/exynos_tmu.c692
-rw-r--r--drivers/thermal/samsung/exynos_tmu.h123
-rw-r--r--drivers/thermal/samsung/exynos_tmu_data.c239
-rw-r--r--drivers/thermal/samsung/exynos_tmu_data.h159
-rw-r--r--drivers/thermal/tegra_soctherm.c476
-rw-r--r--drivers/thermal/thermal_core.c8
-rw-r--r--drivers/thermal/thermal_core.h18
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-thermal-common.c8
-rw-r--r--include/dt-bindings/thermal/tegra124-soctherm.h13
-rw-r--r--include/linux/clock_cooling.h65
-rw-r--r--include/linux/thermal.h73
-rw-r--r--include/uapi/linux/Kbuild1
-rw-r--r--include/uapi/linux/thermal.h35
34 files changed, 2787 insertions, 858 deletions
diff --git a/Documentation/devicetree/bindings/thermal/armada-thermal.txt b/Documentation/devicetree/bindings/thermal/armada-thermal.txt
index 4cf024929a3f..4698e0edc205 100644
--- a/Documentation/devicetree/bindings/thermal/armada-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/armada-thermal.txt
@@ -5,17 +5,9 @@ Required properties:
5- compatible: Should be set to one of the following: 5- compatible: Should be set to one of the following:
6 marvell,armada370-thermal 6 marvell,armada370-thermal
7 marvell,armada375-thermal 7 marvell,armada375-thermal
8 marvell,armada375-z1-thermal
9 marvell,armada380-thermal 8 marvell,armada380-thermal
10 marvell,armadaxp-thermal 9 marvell,armadaxp-thermal
11 10
12 Note: As the name suggests, "marvell,armada375-z1-thermal"
13 applies for the SoC Z1 stepping only. On such stepping
14 some quirks need to be done and the register offset differs
15 from the one in the A0 stepping.
16 The operating system may auto-detect the SoC stepping and
17 update the compatible and register offsets at runtime.
18
19- reg: Device's register space. 11- reg: Device's register space.
20 Two entries are expected, see the examples below. 12 Two entries are expected, see the examples below.
21 The first one is required for the sensor register; 13 The first one is required for the sensor register;
diff --git a/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
new file mode 100644
index 000000000000..ef802de4957a
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/rockchip-thermal.txt
@@ -0,0 +1,68 @@
1* Temperature Sensor ADC (TSADC) on rockchip SoCs
2
3Required properties:
4- compatible : "rockchip,rk3288-tsadc"
5- reg : physical base address of the controller and length of memory mapped
6 region.
7- interrupts : The interrupt number to the cpu. The interrupt specifier format
8 depends on the interrupt controller.
9- clocks : Must contain an entry for each entry in clock-names.
10- clock-names : Shall be "tsadc" for the converter-clock, and "apb_pclk" for
11 the peripheral clock.
12- resets : Must contain an entry for each entry in reset-names.
13 See ../reset/reset.txt for details.
14- reset-names : Must include the name "tsadc-apb".
15- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
16- rockchip,hw-tshut-temp : The hardware-controlled shutdown temperature value.
17- rockchip,hw-tshut-mode : The hardware-controlled shutdown mode 0:CRU 1:GPIO.
18- rockchip,hw-tshut-polarity : The hardware-controlled active polarity 0:LOW
19 1:HIGH.
20
21Exiample:
22tsadc: tsadc@ff280000 {
23 compatible = "rockchip,rk3288-tsadc";
24 reg = <0xff280000 0x100>;
25 interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
26 clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>;
27 clock-names = "tsadc", "apb_pclk";
28 resets = <&cru SRST_TSADC>;
29 reset-names = "tsadc-apb";
30 pinctrl-names = "default";
31 pinctrl-0 = <&otp_out>;
32 #thermal-sensor-cells = <1>;
33 rockchip,hw-tshut-temp = <95000>;
34 rockchip,hw-tshut-mode = <0>;
35 rockchip,hw-tshut-polarity = <0>;
36};
37
38Example: referring to thermal sensors:
39thermal-zones {
40 cpu_thermal: cpu_thermal {
41 polling-delay-passive = <1000>; /* milliseconds */
42 polling-delay = <5000>; /* milliseconds */
43
44 /* sensor ID */
45 thermal-sensors = <&tsadc 1>;
46
47 trips {
48 cpu_alert0: cpu_alert {
49 temperature = <70000>; /* millicelsius */
50 hysteresis = <2000>; /* millicelsius */
51 type = "passive";
52 };
53 cpu_crit: cpu_crit {
54 temperature = <90000>; /* millicelsius */
55 hysteresis = <2000>; /* millicelsius */
56 type = "critical";
57 };
58 };
59
60 cooling-maps {
61 map0 {
62 trip = <&cpu_alert0>;
63 cooling-device =
64 <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
65 };
66 };
67 };
68};
diff --git a/Documentation/devicetree/bindings/thermal/tegra-soctherm.txt b/Documentation/devicetree/bindings/thermal/tegra-soctherm.txt
new file mode 100644
index 000000000000..ecf3ed76cd46
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/tegra-soctherm.txt
@@ -0,0 +1,53 @@
1Tegra124 SOCTHERM thermal management system
2
3The SOCTHERM IP block contains thermal sensors, support for polled
4or interrupt-based thermal monitoring, CPU and GPU throttling based
5on temperature trip points, and handling external overcurrent
6notifications. It is also used to manage emergency shutdown in an
7overheating situation.
8
9Required properties :
10- compatible : "nvidia,tegra124-soctherm".
11- reg : Should contain 1 entry:
12 - SOCTHERM register set
13- interrupts : Defines the interrupt used by SOCTHERM
14- clocks : Must contain an entry for each entry in clock-names.
15 See ../clocks/clock-bindings.txt for details.
16- clock-names : Must include the following entries:
17 - tsensor
18 - soctherm
19- resets : Must contain an entry for each entry in reset-names.
20 See ../reset/reset.txt for details.
21- reset-names : Must include the following entries:
22 - soctherm
23- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description
24 of this property. See <dt-bindings/thermal/tegra124-soctherm.h> for a
25 list of valid values when referring to thermal sensors.
26
27
28Example :
29
30 soctherm@0,700e2000 {
31 compatible = "nvidia,tegra124-soctherm";
32 reg = <0x0 0x700e2000 0x0 0x1000>;
33 interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
34 clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
35 <&tegra_car TEGRA124_CLK_SOC_THERM>;
36 clock-names = "tsensor", "soctherm";
37 resets = <&tegra_car 78>;
38 reset-names = "soctherm";
39
40 #thermal-sensor-cells = <1>;
41 };
42
43Example: referring to thermal sensors :
44
45 thermal-zones {
46 cpu {
47 polling-delay-passive = <1000>;
48 polling-delay = <1000>;
49
50 thermal-sensors =
51 <&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>;
52 };
53 };
diff --git a/MAINTAINERS b/MAINTAINERS
index 68e79dac352f..4507a7e87c00 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9516,6 +9516,7 @@ Q: https://patchwork.kernel.org/project/linux-pm/list/
9516S: Supported 9516S: Supported
9517F: drivers/thermal/ 9517F: drivers/thermal/
9518F: include/linux/thermal.h 9518F: include/linux/thermal.h
9519F: include/uapi/linux/thermal.h
9519F: include/linux/cpu_cooling.h 9520F: include/linux/cpu_cooling.h
9520F: Documentation/devicetree/bindings/thermal/ 9521F: Documentation/devicetree/bindings/thermal/
9521 9522
diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
index 51b373ff1065..4eb540be368f 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
@@ -1942,4 +1942,48 @@
1942 <&tegra_car TEGRA124_CLK_EXTERN1>; 1942 <&tegra_car TEGRA124_CLK_EXTERN1>;
1943 clock-names = "pll_a", "pll_a_out0", "mclk"; 1943 clock-names = "pll_a", "pll_a_out0", "mclk";
1944 }; 1944 };
1945
1946 thermal-zones {
1947 cpu {
1948 trips {
1949 trip@0 {
1950 temperature = <101000>;
1951 hysteresis = <0>;
1952 type = "critical";
1953 };
1954 };
1955
1956 cooling-maps {
1957 /* There are currently no cooling maps because there are no cooling devices */
1958 };
1959 };
1960
1961 mem {
1962 trips {
1963 trip@0 {
1964 temperature = <101000>;
1965 hysteresis = <0>;
1966 type = "critical";
1967 };
1968 };
1969
1970 cooling-maps {
1971 /* There are currently no cooling maps because there are no cooling devices */
1972 };
1973 };
1974
1975 gpu {
1976 trips {
1977 trip@0 {
1978 temperature = <101000>;
1979 hysteresis = <0>;
1980 type = "critical";
1981 };
1982 };
1983
1984 cooling-maps {
1985 /* There are currently no cooling maps because there are no cooling devices */
1986 };
1987 };
1988 };
1945}; 1989};
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index 3ad2e3cf2999..4be06c6ea0c8 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -4,6 +4,7 @@
4#include <dt-bindings/pinctrl/pinctrl-tegra.h> 4#include <dt-bindings/pinctrl/pinctrl-tegra.h>
5#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> 5#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
6#include <dt-bindings/interrupt-controller/arm-gic.h> 6#include <dt-bindings/interrupt-controller/arm-gic.h>
7#include <dt-bindings/thermal/tegra124-soctherm.h>
7 8
8#include "skeleton.dtsi" 9#include "skeleton.dtsi"
9 10
@@ -657,6 +658,18 @@
657 status = "disabled"; 658 status = "disabled";
658 }; 659 };
659 660
661 soctherm: thermal-sensor@0,700e2000 {
662 compatible = "nvidia,tegra124-soctherm";
663 reg = <0x0 0x700e2000 0x0 0x1000>;
664 interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
665 clocks = <&tegra_car TEGRA124_CLK_TSENSOR>,
666 <&tegra_car TEGRA124_CLK_SOC_THERM>;
667 clock-names = "tsensor", "soctherm";
668 resets = <&tegra_car 78>;
669 reset-names = "soctherm";
670 #thermal-sensor-cells = <1>;
671 };
672
660 ahub@0,70300000 { 673 ahub@0,70300000 {
661 compatible = "nvidia,tegra124-ahub"; 674 compatible = "nvidia,tegra124-ahub";
662 reg = <0x0 0x70300000 0x0 0x200>, 675 reg = <0x0 0x70300000 0x0 0x200>,
@@ -898,6 +911,40 @@
898 }; 911 };
899 }; 912 };
900 913
914 thermal-zones {
915 cpu {
916 polling-delay-passive = <1000>;
917 polling-delay = <1000>;
918
919 thermal-sensors =
920 <&soctherm TEGRA124_SOCTHERM_SENSOR_CPU>;
921 };
922
923 mem {
924 polling-delay-passive = <1000>;
925 polling-delay = <1000>;
926
927 thermal-sensors =
928 <&soctherm TEGRA124_SOCTHERM_SENSOR_MEM>;
929 };
930
931 gpu {
932 polling-delay-passive = <1000>;
933 polling-delay = <1000>;
934
935 thermal-sensors =
936 <&soctherm TEGRA124_SOCTHERM_SENSOR_GPU>;
937 };
938
939 pllx {
940 polling-delay-passive = <1000>;
941 polling-delay = <1000>;
942
943 thermal-sensors =
944 <&soctherm TEGRA124_SOCTHERM_SENSOR_PLLX>;
945 };
946 };
947
901 timer { 948 timer {
902 compatible = "arm,armv7-timer"; 949 compatible = "arm,armv7-timer";
903 interrupts = <GIC_PPI 13 950 interrupts = <GIC_PPI 13
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index 6753fd940c76..fe41d5ae7cb2 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -177,6 +177,10 @@ static struct attribute *lm75_attrs[] = {
177}; 177};
178ATTRIBUTE_GROUPS(lm75); 178ATTRIBUTE_GROUPS(lm75);
179 179
180static const struct thermal_zone_of_device_ops lm75_of_thermal_ops = {
181 .get_temp = lm75_read_temp,
182};
183
180/*-----------------------------------------------------------------------*/ 184/*-----------------------------------------------------------------------*/
181 185
182/* device probe and removal */ 186/* device probe and removal */
@@ -296,10 +300,9 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
296 if (IS_ERR(data->hwmon_dev)) 300 if (IS_ERR(data->hwmon_dev))
297 return PTR_ERR(data->hwmon_dev); 301 return PTR_ERR(data->hwmon_dev);
298 302
299 data->tz = thermal_zone_of_sensor_register(data->hwmon_dev, 303 data->tz = thermal_zone_of_sensor_register(data->hwmon_dev, 0,
300 0,
301 data->hwmon_dev, 304 data->hwmon_dev,
302 lm75_read_temp, NULL); 305 &lm75_of_thermal_ops);
303 if (IS_ERR(data->tz)) 306 if (IS_ERR(data->tz))
304 data->tz = NULL; 307 data->tz = NULL;
305 308
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index fd9a945fe8db..112e4d45e4a0 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -486,6 +486,10 @@ static const struct attribute_group ntc_attr_group = {
486 .attrs = ntc_attributes, 486 .attrs = ntc_attributes,
487}; 487};
488 488
489static const struct thermal_zone_of_device_ops ntc_of_thermal_ops = {
490 .get_temp = ntc_read_temp,
491};
492
489static int ntc_thermistor_probe(struct platform_device *pdev) 493static int ntc_thermistor_probe(struct platform_device *pdev)
490{ 494{
491 const struct of_device_id *of_id = 495 const struct of_device_id *of_id =
@@ -579,7 +583,7 @@ static int ntc_thermistor_probe(struct platform_device *pdev)
579 pdev_id->name); 583 pdev_id->name);
580 584
581 data->tz = thermal_zone_of_sensor_register(data->dev, 0, data->dev, 585 data->tz = thermal_zone_of_sensor_register(data->dev, 0, data->dev,
582 ntc_read_temp, NULL); 586 &ntc_of_thermal_ops);
583 if (IS_ERR(data->tz)) { 587 if (IS_ERR(data->tz)) {
584 dev_dbg(&pdev->dev, "Failed to register to thermal fw.\n"); 588 dev_dbg(&pdev->dev, "Failed to register to thermal fw.\n");
585 data->tz = NULL; 589 data->tz = NULL;
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c
index 51719956cc03..ba9f478f64ee 100644
--- a/drivers/hwmon/tmp102.c
+++ b/drivers/hwmon/tmp102.c
@@ -158,6 +158,10 @@ ATTRIBUTE_GROUPS(tmp102);
158#define TMP102_CONFIG (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1) 158#define TMP102_CONFIG (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1)
159#define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL) 159#define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL)
160 160
161static const struct thermal_zone_of_device_ops tmp102_of_thermal_ops = {
162 .get_temp = tmp102_read_temp,
163};
164
161static int tmp102_probe(struct i2c_client *client, 165static int tmp102_probe(struct i2c_client *client,
162 const struct i2c_device_id *id) 166 const struct i2c_device_id *id)
163{ 167{
@@ -215,7 +219,7 @@ static int tmp102_probe(struct i2c_client *client,
215 } 219 }
216 tmp102->hwmon_dev = hwmon_dev; 220 tmp102->hwmon_dev = hwmon_dev;
217 tmp102->tz = thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev, 221 tmp102->tz = thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev,
218 tmp102_read_temp, NULL); 222 &tmp102_of_thermal_ops);
219 if (IS_ERR(tmp102->tz)) 223 if (IS_ERR(tmp102->tz))
220 tmp102->tz = NULL; 224 tmp102->tz = NULL;
221 225
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index f554d25b4399..af40db0df58e 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -112,6 +112,18 @@ config CPU_THERMAL
112 112
113 If you want this support, you should say Y here. 113 If you want this support, you should say Y here.
114 114
115config CLOCK_THERMAL
116 bool "Generic clock cooling support"
117 depends on COMMON_CLK
118 depends on PM_OPP
119 help
120 This entry implements the generic clock cooling mechanism through
121 frequency clipping. Typically used to cool off co-processors. The
122 device that is configured to use this cooling mechanism will be
123 controlled to reduce clock frequency whenever temperature is high.
124
125 If you want this support, you should say Y here.
126
115config THERMAL_EMULATION 127config THERMAL_EMULATION
116 bool "Thermal emulation mode support" 128 bool "Thermal emulation mode support"
117 help 129 help
@@ -143,6 +155,16 @@ config SPEAR_THERMAL
143 Enable this to plug the SPEAr thermal sensor driver into the Linux 155 Enable this to plug the SPEAr thermal sensor driver into the Linux
144 thermal framework. 156 thermal framework.
145 157
158config ROCKCHIP_THERMAL
159 tristate "Rockchip thermal driver"
160 depends on ARCH_ROCKCHIP
161 depends on RESET_CONTROLLER
162 help
163 Rockchip thermal driver provides support for Temperature sensor
164 ADC (TS-ADC) found on Rockchip SoCs. It supports one critical
165 trip point. Cpufreq is used as the cooling device and will throttle
166 CPUs when the Temperature crosses the passive trip point.
167
146config RCAR_THERMAL 168config RCAR_THERMAL
147 tristate "Renesas R-Car thermal driver" 169 tristate "Renesas R-Car thermal driver"
148 depends on ARCH_SHMOBILE || COMPILE_TEST 170 depends on ARCH_SHMOBILE || COMPILE_TEST
@@ -185,6 +207,16 @@ config ARMADA_THERMAL
185 Enable this option if you want to have support for thermal management 207 Enable this option if you want to have support for thermal management
186 controller present in Armada 370 and Armada XP SoC. 208 controller present in Armada 370 and Armada XP SoC.
187 209
210config TEGRA_SOCTHERM
211 tristate "Tegra SOCTHERM thermal management"
212 depends on ARCH_TEGRA
213 help
214 Enable this option for integrated thermal management support on NVIDIA
215 Tegra124 systems-on-chip. The driver supports four thermal zones
216 (CPU, GPU, MEM, PLLX). Cooling devices can be bound to the thermal
217 zones to manage temperatures. This option is also required for the
218 emergency thermal reset (thermtrip) feature to function.
219
188config DB8500_CPUFREQ_COOLING 220config DB8500_CPUFREQ_COOLING
189 tristate "DB8500 cpufreq cooling" 221 tristate "DB8500 cpufreq cooling"
190 depends on ARCH_U8500 222 depends on ARCH_U8500
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 39c4fe87da2f..fa0dc486790f 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -18,8 +18,12 @@ thermal_sys-$(CONFIG_THERMAL_GOV_USER_SPACE) += user_space.o
18# cpufreq cooling 18# cpufreq cooling
19thermal_sys-$(CONFIG_CPU_THERMAL) += cpu_cooling.o 19thermal_sys-$(CONFIG_CPU_THERMAL) += cpu_cooling.o
20 20
21# clock cooling
22thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o
23
21# platform thermal drivers 24# platform thermal drivers
22obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o 25obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
26obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
23obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o 27obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
24obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o 28obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o
25obj-y += samsung/ 29obj-y += samsung/
@@ -34,3 +38,4 @@ obj-$(CONFIG_INTEL_SOC_DTS_THERMAL) += intel_soc_dts_thermal.o
34obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/ 38obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
35obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/ 39obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/
36obj-$(CONFIG_ST_THERMAL) += st/ 40obj-$(CONFIG_ST_THERMAL) += st/
41obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index eaaf59c98ba2..c2556cf5186b 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -35,10 +35,6 @@
35#define PMU_TDC0_OTF_CAL_MASK (0x1 << 30) 35#define PMU_TDC0_OTF_CAL_MASK (0x1 << 30)
36#define PMU_TDC0_START_CAL_MASK (0x1 << 25) 36#define PMU_TDC0_START_CAL_MASK (0x1 << 25)
37 37
38#define A375_Z1_CAL_RESET_LSB 0x8011e214
39#define A375_Z1_CAL_RESET_MSB 0x30a88019
40#define A375_Z1_WORKAROUND_BIT BIT(9)
41
42#define A375_UNIT_CONTROL_SHIFT 27 38#define A375_UNIT_CONTROL_SHIFT 27
43#define A375_UNIT_CONTROL_MASK 0x7 39#define A375_UNIT_CONTROL_MASK 0x7
44#define A375_READOUT_INVERT BIT(15) 40#define A375_READOUT_INVERT BIT(15)
@@ -124,24 +120,12 @@ static void armada375_init_sensor(struct platform_device *pdev,
124 struct armada_thermal_priv *priv) 120 struct armada_thermal_priv *priv)
125{ 121{
126 unsigned long reg; 122 unsigned long reg;
127 bool quirk_needed =
128 !!of_device_is_compatible(pdev->dev.of_node,
129 "marvell,armada375-z1-thermal");
130
131 if (quirk_needed) {
132 /* Ensure these registers have the default (reset) values */
133 writel(A375_Z1_CAL_RESET_LSB, priv->control);
134 writel(A375_Z1_CAL_RESET_MSB, priv->control + 0x4);
135 }
136 123
137 reg = readl(priv->control + 4); 124 reg = readl(priv->control + 4);
138 reg &= ~(A375_UNIT_CONTROL_MASK << A375_UNIT_CONTROL_SHIFT); 125 reg &= ~(A375_UNIT_CONTROL_MASK << A375_UNIT_CONTROL_SHIFT);
139 reg &= ~A375_READOUT_INVERT; 126 reg &= ~A375_READOUT_INVERT;
140 reg &= ~A375_HW_RESETn; 127 reg &= ~A375_HW_RESETn;
141 128
142 if (quirk_needed)
143 reg |= A375_Z1_WORKAROUND_BIT;
144
145 writel(reg, priv->control + 4); 129 writel(reg, priv->control + 4);
146 mdelay(20); 130 mdelay(20);
147 131
@@ -260,10 +244,6 @@ static const struct of_device_id armada_thermal_id_table[] = {
260 .data = &armada375_data, 244 .data = &armada375_data,
261 }, 245 },
262 { 246 {
263 .compatible = "marvell,armada375-z1-thermal",
264 .data = &armada375_data,
265 },
266 {
267 .compatible = "marvell,armada380-thermal", 247 .compatible = "marvell,armada380-thermal",
268 .data = &armada380_data, 248 .data = &armada380_data,
269 }, 249 },
diff --git a/drivers/thermal/clock_cooling.c b/drivers/thermal/clock_cooling.c
new file mode 100644
index 000000000000..1b4ff0f4c716
--- /dev/null
+++ b/drivers/thermal/clock_cooling.c
@@ -0,0 +1,485 @@
1/*
2 * drivers/thermal/clock_cooling.c
3 *
4 * Copyright (C) 2014 Eduardo Valentin <edubezval@gmail.com>
5 *
6 * Copyright (C) 2013 Texas Instruments Inc.
7 * Contact: Eduardo Valentin <eduardo.valentin@ti.com>
8 *
9 * Highly based on cpu_cooling.c.
10 * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com)
11 * Copyright (C) 2012 Amit Daniel <amit.kachhap@linaro.org>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; version 2 of the License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 */
22#include <linux/clk.h>
23#include <linux/cpufreq.h>
24#include <linux/device.h>
25#include <linux/err.h>
26#include <linux/idr.h>
27#include <linux/mutex.h>
28#include <linux/pm_opp.h>
29#include <linux/slab.h>
30#include <linux/thermal.h>
31#include <linux/clock_cooling.h>
32
33/**
34 * struct clock_cooling_device - data for cooling device with clock
35 * @id: unique integer value corresponding to each clock_cooling_device
36 * registered.
37 * @dev: struct device pointer to the device being used to cool off using
38 * clock frequencies.
39 * @cdev: thermal_cooling_device pointer to keep track of the
40 * registered cooling device.
41 * @clk_rate_change_nb: reference to notifier block used to receive clock
42 * rate changes.
43 * @freq_table: frequency table used to keep track of available frequencies.
44 * @clock_state: integer value representing the current state of clock
45 * cooling devices.
46 * @clock_val: integer value representing the absolute value of the clipped
47 * frequency.
48 * @clk: struct clk reference used to enforce clock limits.
49 * @lock: mutex lock to protect this struct.
50 *
51 * This structure is required for keeping information of each
52 * clock_cooling_device registered. In order to prevent corruption of this a
53 * mutex @lock is used.
54 */
55struct clock_cooling_device {
56 int id;
57 struct device *dev;
58 struct thermal_cooling_device *cdev;
59 struct notifier_block clk_rate_change_nb;
60 struct cpufreq_frequency_table *freq_table;
61 unsigned long clock_state;
62 unsigned long clock_val;
63 struct clk *clk;
64 struct mutex lock; /* lock to protect the content of this struct */
65};
66#define to_clock_cooling_device(x) \
67 container_of(x, struct clock_cooling_device, clk_rate_change_nb)
68static DEFINE_IDR(clock_idr);
69static DEFINE_MUTEX(cooling_clock_lock);
70
71/**
72 * clock_cooling_get_idr - function to get an unique id.
73 * @id: int * value generated by this function.
74 *
75 * This function will populate @id with an unique
76 * id, using the idr API.
77 *
78 * Return: 0 on success, an error code on failure.
79 */
80static int clock_cooling_get_idr(int *id)
81{
82 int ret;
83
84 mutex_lock(&cooling_clock_lock);
85 ret = idr_alloc(&clock_idr, NULL, 0, 0, GFP_KERNEL);
86 mutex_unlock(&cooling_clock_lock);
87 if (unlikely(ret < 0))
88 return ret;
89 *id = ret;
90
91 return 0;
92}
93
94/**
95 * release_idr - function to free the unique id.
96 * @id: int value representing the unique id.
97 */
98static void release_idr(int id)
99{
100 mutex_lock(&cooling_clock_lock);
101 idr_remove(&clock_idr, id);
102 mutex_unlock(&cooling_clock_lock);
103}
104
105/* Below code defines functions to be used for clock as cooling device */
106
107enum clock_cooling_property {
108 GET_LEVEL,
109 GET_FREQ,
110 GET_MAXL,
111};
112
113/**
114 * clock_cooling_get_property - fetch a property of interest for a give cpu.
115 * @ccdev: clock cooling device reference
116 * @input: query parameter
117 * @output: query return
118 * @property: type of query (frequency, level, max level)
119 *
120 * This is the common function to
121 * 1. get maximum clock cooling states
122 * 2. translate frequency to cooling state
123 * 3. translate cooling state to frequency
124 * Note that the code may be not in good shape
125 * but it is written in this way in order to:
126 * a) reduce duplicate code as most of the code can be shared.
127 * b) make sure the logic is consistent when translating between
128 * cooling states and frequencies.
129 *
130 * Return: 0 on success, -EINVAL when invalid parameters are passed.
131 */
132static int clock_cooling_get_property(struct clock_cooling_device *ccdev,
133 unsigned long input,
134 unsigned long *output,
135 enum clock_cooling_property property)
136{
137 int i;
138 unsigned long max_level = 0, level = 0;
139 unsigned int freq = CPUFREQ_ENTRY_INVALID;
140 int descend = -1;
141 struct cpufreq_frequency_table *pos, *table = ccdev->freq_table;
142
143 if (!output)
144 return -EINVAL;
145
146 if (!table)
147 return -EINVAL;
148
149 cpufreq_for_each_valid_entry(pos, table) {
150 /* ignore duplicate entry */
151 if (freq == pos->frequency)
152 continue;
153
154 /* get the frequency order */
155 if (freq != CPUFREQ_ENTRY_INVALID && descend == -1)
156 descend = freq > pos->frequency;
157
158 freq = pos->frequency;
159 max_level++;
160 }
161
162 /* No valid cpu frequency entry */
163 if (max_level == 0)
164 return -EINVAL;
165
166 /* max_level is an index, not a counter */
167 max_level--;
168
169 /* get max level */
170 if (property == GET_MAXL) {
171 *output = max_level;
172 return 0;
173 }
174
175 if (property == GET_FREQ)
176 level = descend ? input : (max_level - input);
177
178 i = 0;
179 cpufreq_for_each_valid_entry(pos, table) {
180 /* ignore duplicate entry */
181 if (freq == pos->frequency)
182 continue;
183
184 /* now we have a valid frequency entry */
185 freq = pos->frequency;
186
187 if (property == GET_LEVEL && (unsigned int)input == freq) {
188 /* get level by frequency */
189 *output = descend ? i : (max_level - i);
190 return 0;
191 }
192 if (property == GET_FREQ && level == i) {
193 /* get frequency by level */
194 *output = freq;
195 return 0;
196 }
197 i++;
198 }
199
200 return -EINVAL;
201}
202
203/**
204 * clock_cooling_get_level - return the cooling level of given clock cooling.
205 * @cdev: reference of a thermal cooling device of used as clock cooling device
206 * @freq: the frequency of interest
207 *
208 * This function will match the cooling level corresponding to the
209 * requested @freq and return it.
210 *
211 * Return: The matched cooling level on success or THERMAL_CSTATE_INVALID
212 * otherwise.
213 */
214unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev,
215 unsigned long freq)
216{
217 struct clock_cooling_device *ccdev = cdev->devdata;
218 unsigned long val;
219
220 if (clock_cooling_get_property(ccdev, (unsigned long)freq, &val,
221 GET_LEVEL))
222 return THERMAL_CSTATE_INVALID;
223
224 return val;
225}
226EXPORT_SYMBOL_GPL(clock_cooling_get_level);
227
228/**
229 * clock_cooling_get_frequency - get the absolute value of frequency from level.
230 * @ccdev: clock cooling device reference
231 * @level: cooling level
232 *
233 * This function matches cooling level with frequency. Based on a cooling level
234 * of frequency, equals cooling state of cpu cooling device, it will return
235 * the corresponding frequency.
236 * e.g level=0 --> 1st MAX FREQ, level=1 ---> 2nd MAX FREQ, .... etc
237 *
238 * Return: 0 on error, the corresponding frequency otherwise.
239 */
240static unsigned long
241clock_cooling_get_frequency(struct clock_cooling_device *ccdev,
242 unsigned long level)
243{
244 int ret = 0;
245 unsigned long freq;
246
247 ret = clock_cooling_get_property(ccdev, level, &freq, GET_FREQ);
248 if (ret)
249 return 0;
250
251 return freq;
252}
253
254/**
255 * clock_cooling_apply - function to apply frequency clipping.
256 * @ccdev: clock_cooling_device pointer containing frequency clipping data.
257 * @cooling_state: value of the cooling state.
258 *
259 * Function used to make sure the clock layer is aware of current thermal
260 * limits. The limits are applied by updating the clock rate in case it is
261 * higher than the corresponding frequency based on the requested cooling_state.
262 *
263 * Return: 0 on success, an error code otherwise (-EINVAL in case wrong
264 * cooling state).
265 */
266static int clock_cooling_apply(struct clock_cooling_device *ccdev,
267 unsigned long cooling_state)
268{
269 unsigned long clip_freq, cur_freq;
270 int ret = 0;
271
272 /* Here we write the clipping */
273 /* Check if the old cooling action is same as new cooling action */
274 if (ccdev->clock_state == cooling_state)
275 return 0;
276
277 clip_freq = clock_cooling_get_frequency(ccdev, cooling_state);
278 if (!clip_freq)
279 return -EINVAL;
280
281 cur_freq = clk_get_rate(ccdev->clk);
282
283 mutex_lock(&ccdev->lock);
284 ccdev->clock_state = cooling_state;
285 ccdev->clock_val = clip_freq;
286 /* enforce clock level */
287 if (cur_freq > clip_freq)
288 ret = clk_set_rate(ccdev->clk, clip_freq);
289 mutex_unlock(&ccdev->lock);
290
291 return ret;
292}
293
294/**
295 * clock_cooling_clock_notifier - notifier callback on clock rate changes.
296 * @nb: struct notifier_block * with callback info.
297 * @event: value showing clock event for which this function invoked.
298 * @data: callback-specific data
299 *
300 * Callback to hijack the notification on clock transition.
301 * Every time there is a clock change, we intercept all pre change events
302 * and block the transition in case the new rate infringes thermal limits.
303 *
304 * Return: NOTIFY_DONE (success) or NOTIFY_BAD (new_rate > thermal limit).
305 */
306static int clock_cooling_clock_notifier(struct notifier_block *nb,
307 unsigned long event, void *data)
308{
309 struct clk_notifier_data *ndata = data;
310 struct clock_cooling_device *ccdev = to_clock_cooling_device(nb);
311
312 switch (event) {
313 case PRE_RATE_CHANGE:
314 /*
315 * checks on current state
316 * TODO: current method is not best we can find as it
317 * allows possibly voltage transitions, in case DVFS
318 * layer is also hijacking clock pre notifications.
319 */
320 if (ndata->new_rate > ccdev->clock_val)
321 return NOTIFY_BAD;
322 /* fall through */
323 case POST_RATE_CHANGE:
324 case ABORT_RATE_CHANGE:
325 default:
326 return NOTIFY_DONE;
327 }
328}
329
330/* clock cooling device thermal callback functions are defined below */
331
332/**
333 * clock_cooling_get_max_state - callback function to get the max cooling state.
334 * @cdev: thermal cooling device pointer.
335 * @state: fill this variable with the max cooling state.
336 *
337 * Callback for the thermal cooling device to return the clock
338 * max cooling state.
339 *
340 * Return: 0 on success, an error code otherwise.
341 */
342static int clock_cooling_get_max_state(struct thermal_cooling_device *cdev,
343 unsigned long *state)
344{
345 struct clock_cooling_device *ccdev = cdev->devdata;
346 unsigned long count = 0;
347 int ret;
348
349 ret = clock_cooling_get_property(ccdev, 0, &count, GET_MAXL);
350 if (!ret)
351 *state = count;
352
353 return ret;
354}
355
356/**
357 * clock_cooling_get_cur_state - function to get the current cooling state.
358 * @cdev: thermal cooling device pointer.
359 * @state: fill this variable with the current cooling state.
360 *
361 * Callback for the thermal cooling device to return the clock
362 * current cooling state.
363 *
364 * Return: 0 (success)
365 */
366static int clock_cooling_get_cur_state(struct thermal_cooling_device *cdev,
367 unsigned long *state)
368{
369 struct clock_cooling_device *ccdev = cdev->devdata;
370
371 *state = ccdev->clock_state;
372
373 return 0;
374}
375
376/**
377 * clock_cooling_set_cur_state - function to set the current cooling state.
378 * @cdev: thermal cooling device pointer.
379 * @state: set this variable to the current cooling state.
380 *
381 * Callback for the thermal cooling device to change the clock cooling
382 * current cooling state.
383 *
384 * Return: 0 on success, an error code otherwise.
385 */
386static int clock_cooling_set_cur_state(struct thermal_cooling_device *cdev,
387 unsigned long state)
388{
389 struct clock_cooling_device *clock_device = cdev->devdata;
390
391 return clock_cooling_apply(clock_device, state);
392}
393
394/* Bind clock callbacks to thermal cooling device ops */
395static struct thermal_cooling_device_ops const clock_cooling_ops = {
396 .get_max_state = clock_cooling_get_max_state,
397 .get_cur_state = clock_cooling_get_cur_state,
398 .set_cur_state = clock_cooling_set_cur_state,
399};
400
401/**
402 * clock_cooling_register - function to create clock cooling device.
403 * @dev: struct device pointer to the device used as clock cooling device.
404 * @clock_name: string containing the clock used as cooling mechanism.
405 *
406 * This interface function registers the clock cooling device with the name
407 * "thermal-clock-%x". The cooling device is based on clock frequencies.
408 * The struct device is assumed to be capable of DVFS transitions.
409 * The OPP layer is used to fetch and fill the available frequencies for
410 * the referred device. The ordered frequency table is used to control
411 * the clock cooling device cooling states and to limit clock transitions
412 * based on the cooling state requested by the thermal framework.
413 *
414 * Return: a valid struct thermal_cooling_device pointer on success,
415 * on failure, it returns a corresponding ERR_PTR().
416 */
417struct thermal_cooling_device *
418clock_cooling_register(struct device *dev, const char *clock_name)
419{
420 struct thermal_cooling_device *cdev;
421 struct clock_cooling_device *ccdev = NULL;
422 char dev_name[THERMAL_NAME_LENGTH];
423 int ret = 0;
424
425 ccdev = devm_kzalloc(dev, sizeof(*ccdev), GFP_KERNEL);
426 if (!ccdev)
427 return ERR_PTR(-ENOMEM);
428
429 ccdev->dev = dev;
430 ccdev->clk = devm_clk_get(dev, clock_name);
431 if (IS_ERR(ccdev->clk))
432 return ERR_CAST(ccdev->clk);
433
434 ret = clock_cooling_get_idr(&ccdev->id);
435 if (ret)
436 return ERR_PTR(-EINVAL);
437
438 snprintf(dev_name, sizeof(dev_name), "thermal-clock-%d", ccdev->id);
439
440 cdev = thermal_cooling_device_register(dev_name, ccdev,
441 &clock_cooling_ops);
442 if (IS_ERR(cdev)) {
443 release_idr(ccdev->id);
444 return ERR_PTR(-EINVAL);
445 }
446 ccdev->cdev = cdev;
447 ccdev->clk_rate_change_nb.notifier_call = clock_cooling_clock_notifier;
448
449 /* Assuming someone has already filled the opp table for this device */
450 ret = dev_pm_opp_init_cpufreq_table(dev, &ccdev->freq_table);
451 if (ret) {
452 release_idr(ccdev->id);
453 return ERR_PTR(ret);
454 }
455 ccdev->clock_state = 0;
456 ccdev->clock_val = clock_cooling_get_frequency(ccdev, 0);
457
458 clk_notifier_register(ccdev->clk, &ccdev->clk_rate_change_nb);
459
460 return cdev;
461}
462EXPORT_SYMBOL_GPL(clock_cooling_register);
463
464/**
465 * clock_cooling_unregister - function to remove clock cooling device.
466 * @cdev: thermal cooling device pointer.
467 *
468 * This interface function unregisters the "thermal-clock-%x" cooling device.
469 */
470void clock_cooling_unregister(struct thermal_cooling_device *cdev)
471{
472 struct clock_cooling_device *ccdev;
473
474 if (!cdev)
475 return;
476
477 ccdev = cdev->devdata;
478
479 clk_notifier_unregister(ccdev->clk, &ccdev->clk_rate_change_nb);
480 dev_pm_opp_free_cpufreq_table(ccdev->dev, &ccdev->freq_table);
481
482 thermal_cooling_device_unregister(ccdev->cdev);
483 release_idr(ccdev->id);
484}
485EXPORT_SYMBOL_GPL(clock_cooling_unregister);
diff --git a/drivers/thermal/int340x_thermal/acpi_thermal_rel.c b/drivers/thermal/int340x_thermal/acpi_thermal_rel.c
index 0d8db808f0ae..e4e61b3fb11e 100644
--- a/drivers/thermal/int340x_thermal/acpi_thermal_rel.c
+++ b/drivers/thermal/int340x_thermal/acpi_thermal_rel.c
@@ -131,6 +131,8 @@ int acpi_parse_trt(acpi_handle handle, int *trt_count, struct trt **trtp,
131 pr_warn("Failed to get target ACPI device\n"); 131 pr_warn("Failed to get target ACPI device\n");
132 } 132 }
133 133
134 result = 0;
135
134 *trtp = trts; 136 *trtp = trts;
135 /* don't count bad entries */ 137 /* don't count bad entries */
136 *trt_count -= nr_bad_entries; 138 *trt_count -= nr_bad_entries;
@@ -317,21 +319,21 @@ static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd,
317{ 319{
318 int ret = 0; 320 int ret = 0;
319 unsigned long length = 0; 321 unsigned long length = 0;
320 unsigned long count = 0; 322 int count = 0;
321 char __user *arg = (void __user *)__arg; 323 char __user *arg = (void __user *)__arg;
322 struct trt *trts; 324 struct trt *trts;
323 struct art *arts; 325 struct art *arts;
324 326
325 switch (cmd) { 327 switch (cmd) {
326 case ACPI_THERMAL_GET_TRT_COUNT: 328 case ACPI_THERMAL_GET_TRT_COUNT:
327 ret = acpi_parse_trt(acpi_thermal_rel_handle, (int *)&count, 329 ret = acpi_parse_trt(acpi_thermal_rel_handle, &count,
328 &trts, false); 330 &trts, false);
329 kfree(trts); 331 kfree(trts);
330 if (!ret) 332 if (!ret)
331 return put_user(count, (unsigned long __user *)__arg); 333 return put_user(count, (unsigned long __user *)__arg);
332 return ret; 334 return ret;
333 case ACPI_THERMAL_GET_TRT_LEN: 335 case ACPI_THERMAL_GET_TRT_LEN:
334 ret = acpi_parse_trt(acpi_thermal_rel_handle, (int *)&count, 336 ret = acpi_parse_trt(acpi_thermal_rel_handle, &count,
335 &trts, false); 337 &trts, false);
336 kfree(trts); 338 kfree(trts);
337 length = count * sizeof(union trt_object); 339 length = count * sizeof(union trt_object);
@@ -341,14 +343,14 @@ static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd,
341 case ACPI_THERMAL_GET_TRT: 343 case ACPI_THERMAL_GET_TRT:
342 return fill_trt(arg); 344 return fill_trt(arg);
343 case ACPI_THERMAL_GET_ART_COUNT: 345 case ACPI_THERMAL_GET_ART_COUNT:
344 ret = acpi_parse_art(acpi_thermal_rel_handle, (int *)&count, 346 ret = acpi_parse_art(acpi_thermal_rel_handle, &count,
345 &arts, false); 347 &arts, false);
346 kfree(arts); 348 kfree(arts);
347 if (!ret) 349 if (!ret)
348 return put_user(count, (unsigned long __user *)__arg); 350 return put_user(count, (unsigned long __user *)__arg);
349 return ret; 351 return ret;
350 case ACPI_THERMAL_GET_ART_LEN: 352 case ACPI_THERMAL_GET_ART_LEN:
351 ret = acpi_parse_art(acpi_thermal_rel_handle, (int *)&count, 353 ret = acpi_parse_art(acpi_thermal_rel_handle, &count,
352 &arts, false); 354 &arts, false);
353 kfree(arts); 355 kfree(arts);
354 length = count * sizeof(union art_object); 356 length = count * sizeof(union art_object);
diff --git a/drivers/thermal/int340x_thermal/int3400_thermal.c b/drivers/thermal/int340x_thermal/int3400_thermal.c
index edc1cce117ba..dcb306ea14a4 100644
--- a/drivers/thermal/int340x_thermal/int3400_thermal.c
+++ b/drivers/thermal/int340x_thermal/int3400_thermal.c
@@ -43,6 +43,74 @@ struct int3400_thermal_priv {
43 struct trt *trts; 43 struct trt *trts;
44 u8 uuid_bitmap; 44 u8 uuid_bitmap;
45 int rel_misc_dev_res; 45 int rel_misc_dev_res;
46 int current_uuid_index;
47};
48
49static ssize_t available_uuids_show(struct device *dev,
50 struct device_attribute *attr,
51 char *buf)
52{
53 struct platform_device *pdev = to_platform_device(dev);
54 struct int3400_thermal_priv *priv = platform_get_drvdata(pdev);
55 int i;
56 int length = 0;
57
58 for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; i++) {
59 if (priv->uuid_bitmap & (1 << i))
60 if (PAGE_SIZE - length > 0)
61 length += snprintf(&buf[length],
62 PAGE_SIZE - length,
63 "%s\n",
64 int3400_thermal_uuids[i]);
65 }
66
67 return length;
68}
69
70static ssize_t current_uuid_show(struct device *dev,
71 struct device_attribute *devattr, char *buf)
72{
73 struct platform_device *pdev = to_platform_device(dev);
74 struct int3400_thermal_priv *priv = platform_get_drvdata(pdev);
75
76 if (priv->uuid_bitmap & (1 << priv->current_uuid_index))
77 return sprintf(buf, "%s\n",
78 int3400_thermal_uuids[priv->current_uuid_index]);
79 else
80 return sprintf(buf, "INVALID\n");
81}
82
83static ssize_t current_uuid_store(struct device *dev,
84 struct device_attribute *attr,
85 const char *buf, size_t count)
86{
87 struct platform_device *pdev = to_platform_device(dev);
88 struct int3400_thermal_priv *priv = platform_get_drvdata(pdev);
89 int i;
90
91 for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; ++i) {
92 if ((priv->uuid_bitmap & (1 << i)) &&
93 !(strncmp(buf, int3400_thermal_uuids[i],
94 sizeof(int3400_thermal_uuids[i]) - 1))) {
95 priv->current_uuid_index = i;
96 return count;
97 }
98 }
99
100 return -EINVAL;
101}
102
103static DEVICE_ATTR(current_uuid, 0644, current_uuid_show, current_uuid_store);
104static DEVICE_ATTR_RO(available_uuids);
105static struct attribute *uuid_attrs[] = {
106 &dev_attr_available_uuids.attr,
107 &dev_attr_current_uuid.attr,
108 NULL
109};
110
111static struct attribute_group uuid_attribute_group = {
112 .attrs = uuid_attrs,
113 .name = "uuids"
46}; 114};
47 115
48static int int3400_thermal_get_uuids(struct int3400_thermal_priv *priv) 116static int int3400_thermal_get_uuids(struct int3400_thermal_priv *priv)
@@ -160,9 +228,9 @@ static int int3400_thermal_set_mode(struct thermal_zone_device *thermal,
160 228
161 if (enable != priv->mode) { 229 if (enable != priv->mode) {
162 priv->mode = enable; 230 priv->mode = enable;
163 /* currently, only PASSIVE COOLING is supported */
164 result = int3400_thermal_run_osc(priv->adev->handle, 231 result = int3400_thermal_run_osc(priv->adev->handle,
165 INT3400_THERMAL_PASSIVE_1, enable); 232 priv->current_uuid_index,
233 enable);
166 } 234 }
167 return result; 235 return result;
168} 236}
@@ -223,7 +291,14 @@ static int int3400_thermal_probe(struct platform_device *pdev)
223 priv->rel_misc_dev_res = acpi_thermal_rel_misc_device_add( 291 priv->rel_misc_dev_res = acpi_thermal_rel_misc_device_add(
224 priv->adev->handle); 292 priv->adev->handle);
225 293
294 result = sysfs_create_group(&pdev->dev.kobj, &uuid_attribute_group);
295 if (result)
296 goto free_zone;
297
226 return 0; 298 return 0;
299
300free_zone:
301 thermal_zone_device_unregister(priv->thermal);
227free_trt: 302free_trt:
228 kfree(priv->trts); 303 kfree(priv->trts);
229free_art: 304free_art:
@@ -240,6 +315,7 @@ static int int3400_thermal_remove(struct platform_device *pdev)
240 if (!priv->rel_misc_dev_res) 315 if (!priv->rel_misc_dev_res)
241 acpi_thermal_rel_misc_device_remove(priv->adev->handle); 316 acpi_thermal_rel_misc_device_remove(priv->adev->handle);
242 317
318 sysfs_remove_group(&pdev->dev.kobj, &uuid_attribute_group);
243 thermal_zone_device_unregister(priv->thermal); 319 thermal_zone_device_unregister(priv->thermal);
244 kfree(priv->trts); 320 kfree(priv->trts);
245 kfree(priv->arts); 321 kfree(priv->arts);
diff --git a/drivers/thermal/int340x_thermal/int3403_thermal.c b/drivers/thermal/int340x_thermal/int3403_thermal.c
index 6e9fb62eb817..1bfa6a69e77a 100644
--- a/drivers/thermal/int340x_thermal/int3403_thermal.c
+++ b/drivers/thermal/int340x_thermal/int3403_thermal.c
@@ -293,8 +293,7 @@ static int int3403_sensor_add(struct int3403_priv *priv)
293 return 0; 293 return 0;
294 294
295 err_free_obj: 295 err_free_obj:
296 if (obj->tzone) 296 thermal_zone_device_unregister(obj->tzone);
297 thermal_zone_device_unregister(obj->tzone);
298 return result; 297 return result;
299} 298}
300 299
@@ -471,7 +470,6 @@ static struct platform_driver int3403_driver = {
471 .remove = int3403_remove, 470 .remove = int3403_remove,
472 .driver = { 471 .driver = {
473 .name = "int3403 thermal", 472 .name = "int3403 thermal",
474 .owner = THIS_MODULE,
475 .acpi_match_table = int3403_device_ids, 473 .acpi_match_table = int3403_device_ids,
476 }, 474 },
477}; 475};
diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c
index 95cb7fc20e17..b46c706e1cac 100644
--- a/drivers/thermal/intel_powerclamp.c
+++ b/drivers/thermal/intel_powerclamp.c
@@ -689,6 +689,7 @@ static const struct x86_cpu_id intel_powerclamp_ids[] = {
689 { X86_VENDOR_INTEL, 6, 0x3f}, 689 { X86_VENDOR_INTEL, 6, 0x3f},
690 { X86_VENDOR_INTEL, 6, 0x45}, 690 { X86_VENDOR_INTEL, 6, 0x45},
691 { X86_VENDOR_INTEL, 6, 0x46}, 691 { X86_VENDOR_INTEL, 6, 0x46},
692 { X86_VENDOR_INTEL, 6, 0x4c},
692 {} 693 {}
693}; 694};
694MODULE_DEVICE_TABLE(x86cpu, intel_powerclamp_ids); 695MODULE_DEVICE_TABLE(x86cpu, intel_powerclamp_ids);
diff --git a/drivers/thermal/intel_soc_dts_thermal.c b/drivers/thermal/intel_soc_dts_thermal.c
index a6a0a18ec0aa..5580f5b24eb9 100644
--- a/drivers/thermal/intel_soc_dts_thermal.c
+++ b/drivers/thermal/intel_soc_dts_thermal.c
@@ -360,6 +360,9 @@ static void proc_thermal_interrupt(void)
360 u32 sticky_out; 360 u32 sticky_out;
361 int status; 361 int status;
362 u32 ptmc_out; 362 u32 ptmc_out;
363 unsigned long flags;
364
365 spin_lock_irqsave(&intr_notify_lock, flags);
363 366
364 /* Clear APIC interrupt */ 367 /* Clear APIC interrupt */
365 status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ, 368 status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
@@ -378,21 +381,20 @@ static void proc_thermal_interrupt(void)
378 /* reset sticky bit */ 381 /* reset sticky bit */
379 status = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE, 382 status = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
380 SOC_DTS_OFFSET_PTTSS, sticky_out); 383 SOC_DTS_OFFSET_PTTSS, sticky_out);
384 spin_unlock_irqrestore(&intr_notify_lock, flags);
385
381 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { 386 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
382 pr_debug("TZD update for zone %d\n", i); 387 pr_debug("TZD update for zone %d\n", i);
383 thermal_zone_device_update(soc_dts[i]->tzone); 388 thermal_zone_device_update(soc_dts[i]->tzone);
384 } 389 }
385 } 390 } else
391 spin_unlock_irqrestore(&intr_notify_lock, flags);
386 392
387} 393}
388 394
389static irqreturn_t soc_irq_thread_fn(int irq, void *dev_data) 395static irqreturn_t soc_irq_thread_fn(int irq, void *dev_data)
390{ 396{
391 unsigned long flags;
392
393 spin_lock_irqsave(&intr_notify_lock, flags);
394 proc_thermal_interrupt(); 397 proc_thermal_interrupt();
395 spin_unlock_irqrestore(&intr_notify_lock, flags);
396 pr_debug("proc_thermal_interrupt\n"); 398 pr_debug("proc_thermal_interrupt\n");
397 399
398 return IRQ_HANDLED; 400 return IRQ_HANDLED;
diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index 62143ba31001..e145b66df444 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -30,27 +30,13 @@
30#include <linux/err.h> 30#include <linux/err.h>
31#include <linux/export.h> 31#include <linux/export.h>
32#include <linux/string.h> 32#include <linux/string.h>
33#include <linux/thermal.h>
33 34
34#include "thermal_core.h" 35#include "thermal_core.h"
35 36
36/*** Private data structures to represent thermal device tree data ***/ 37/*** Private data structures to represent thermal device tree data ***/
37 38
38/** 39/**
39 * struct __thermal_trip - representation of a point in temperature domain
40 * @np: pointer to struct device_node that this trip point was created from
41 * @temperature: temperature value in miliCelsius
42 * @hysteresis: relative hysteresis in miliCelsius
43 * @type: trip point type
44 */
45
46struct __thermal_trip {
47 struct device_node *np;
48 unsigned long int temperature;
49 unsigned long int hysteresis;
50 enum thermal_trip_type type;
51};
52
53/**
54 * struct __thermal_bind_param - a match between trip and cooling device 40 * struct __thermal_bind_param - a match between trip and cooling device
55 * @cooling_device: a pointer to identify the referred cooling device 41 * @cooling_device: a pointer to identify the referred cooling device
56 * @trip_id: the trip point index 42 * @trip_id: the trip point index
@@ -77,8 +63,7 @@ struct __thermal_bind_params {
77 * @num_tbps: number of thermal bind params 63 * @num_tbps: number of thermal bind params
78 * @tbps: an array of thermal bind params (0..num_tbps - 1) 64 * @tbps: an array of thermal bind params (0..num_tbps - 1)
79 * @sensor_data: sensor private data used while reading temperature and trend 65 * @sensor_data: sensor private data used while reading temperature and trend
80 * @get_temp: sensor callback to read temperature 66 * @ops: set of callbacks to handle the thermal zone based on DT
81 * @get_trend: sensor callback to read temperature trend
82 */ 67 */
83 68
84struct __thermal_zone { 69struct __thermal_zone {
@@ -88,7 +73,7 @@ struct __thermal_zone {
88 73
89 /* trip data */ 74 /* trip data */
90 int ntrips; 75 int ntrips;
91 struct __thermal_trip *trips; 76 struct thermal_trip *trips;
92 77
93 /* cooling binding data */ 78 /* cooling binding data */
94 int num_tbps; 79 int num_tbps;
@@ -96,8 +81,7 @@ struct __thermal_zone {
96 81
97 /* sensor interface */ 82 /* sensor interface */
98 void *sensor_data; 83 void *sensor_data;
99 int (*get_temp)(void *, long *); 84 const struct thermal_zone_of_device_ops *ops;
100 int (*get_trend)(void *, long *);
101}; 85};
102 86
103/*** DT thermal zone device callbacks ***/ 87/*** DT thermal zone device callbacks ***/
@@ -107,10 +91,96 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz,
107{ 91{
108 struct __thermal_zone *data = tz->devdata; 92 struct __thermal_zone *data = tz->devdata;
109 93
110 if (!data->get_temp) 94 if (!data->ops->get_temp)
111 return -EINVAL; 95 return -EINVAL;
112 96
113 return data->get_temp(data->sensor_data, temp); 97 return data->ops->get_temp(data->sensor_data, temp);
98}
99
100/**
101 * of_thermal_get_ntrips - function to export number of available trip
102 * points.
103 * @tz: pointer to a thermal zone
104 *
105 * This function is a globally visible wrapper to get number of trip points
106 * stored in the local struct __thermal_zone
107 *
108 * Return: number of available trip points, -ENODEV when data not available
109 */
110int of_thermal_get_ntrips(struct thermal_zone_device *tz)
111{
112 struct __thermal_zone *data = tz->devdata;
113
114 if (!data || IS_ERR(data))
115 return -ENODEV;
116
117 return data->ntrips;
118}
119EXPORT_SYMBOL_GPL(of_thermal_get_ntrips);
120
121/**
122 * of_thermal_is_trip_valid - function to check if trip point is valid
123 *
124 * @tz: pointer to a thermal zone
125 * @trip: trip point to evaluate
126 *
127 * This function is responsible for checking if passed trip point is valid
128 *
129 * Return: true if trip point is valid, false otherwise
130 */
131bool of_thermal_is_trip_valid(struct thermal_zone_device *tz, int trip)
132{
133 struct __thermal_zone *data = tz->devdata;
134
135 if (!data || trip >= data->ntrips || trip < 0)
136 return false;
137
138 return true;
139}
140EXPORT_SYMBOL_GPL(of_thermal_is_trip_valid);
141
142/**
143 * of_thermal_get_trip_points - function to get access to a globally exported
144 * trip points
145 *
146 * @tz: pointer to a thermal zone
147 *
148 * This function provides a pointer to trip points table
149 *
150 * Return: pointer to trip points table, NULL otherwise
151 */
152const struct thermal_trip * const
153of_thermal_get_trip_points(struct thermal_zone_device *tz)
154{
155 struct __thermal_zone *data = tz->devdata;
156
157 if (!data)
158 return NULL;
159
160 return data->trips;
161}
162EXPORT_SYMBOL_GPL(of_thermal_get_trip_points);
163
164/**
165 * of_thermal_set_emul_temp - function to set emulated temperature
166 *
167 * @tz: pointer to a thermal zone
168 * @temp: temperature to set
169 *
170 * This function gives the ability to set emulated value of temperature,
171 * which is handy for debugging
172 *
173 * Return: zero on success, error code otherwise
174 */
175static int of_thermal_set_emul_temp(struct thermal_zone_device *tz,
176 unsigned long temp)
177{
178 struct __thermal_zone *data = tz->devdata;
179
180 if (!data->ops || !data->ops->set_emul_temp)
181 return -EINVAL;
182
183 return data->ops->set_emul_temp(data->sensor_data, temp);
114} 184}
115 185
116static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip, 186static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
@@ -120,10 +190,10 @@ static int of_thermal_get_trend(struct thermal_zone_device *tz, int trip,
120 long dev_trend; 190 long dev_trend;
121 int r; 191 int r;
122 192
123 if (!data->get_trend) 193 if (!data->ops->get_trend)
124 return -EINVAL; 194 return -EINVAL;
125 195
126 r = data->get_trend(data->sensor_data, &dev_trend); 196 r = data->ops->get_trend(data->sensor_data, &dev_trend);
127 if (r) 197 if (r)
128 return r; 198 return r;
129 199
@@ -324,8 +394,7 @@ static struct thermal_zone_device_ops of_thermal_ops = {
324static struct thermal_zone_device * 394static struct thermal_zone_device *
325thermal_zone_of_add_sensor(struct device_node *zone, 395thermal_zone_of_add_sensor(struct device_node *zone,
326 struct device_node *sensor, void *data, 396 struct device_node *sensor, void *data,
327 int (*get_temp)(void *, long *), 397 const struct thermal_zone_of_device_ops *ops)
328 int (*get_trend)(void *, long *))
329{ 398{
330 struct thermal_zone_device *tzd; 399 struct thermal_zone_device *tzd;
331 struct __thermal_zone *tz; 400 struct __thermal_zone *tz;
@@ -336,13 +405,16 @@ thermal_zone_of_add_sensor(struct device_node *zone,
336 405
337 tz = tzd->devdata; 406 tz = tzd->devdata;
338 407
408 if (!ops)
409 return ERR_PTR(-EINVAL);
410
339 mutex_lock(&tzd->lock); 411 mutex_lock(&tzd->lock);
340 tz->get_temp = get_temp; 412 tz->ops = ops;
341 tz->get_trend = get_trend;
342 tz->sensor_data = data; 413 tz->sensor_data = data;
343 414
344 tzd->ops->get_temp = of_thermal_get_temp; 415 tzd->ops->get_temp = of_thermal_get_temp;
345 tzd->ops->get_trend = of_thermal_get_trend; 416 tzd->ops->get_trend = of_thermal_get_trend;
417 tzd->ops->set_emul_temp = of_thermal_set_emul_temp;
346 mutex_unlock(&tzd->lock); 418 mutex_unlock(&tzd->lock);
347 419
348 return tzd; 420 return tzd;
@@ -356,8 +428,7 @@ thermal_zone_of_add_sensor(struct device_node *zone,
356 * than one sensors 428 * than one sensors
357 * @data: a private pointer (owned by the caller) that will be passed 429 * @data: a private pointer (owned by the caller) that will be passed
358 * back, when a temperature reading is needed. 430 * back, when a temperature reading is needed.
359 * @get_temp: a pointer to a function that reads the sensor temperature. 431 * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp.
360 * @get_trend: a pointer to a function that reads the sensor temperature trend.
361 * 432 *
362 * This function will search the list of thermal zones described in device 433 * This function will search the list of thermal zones described in device
363 * tree and look for the zone that refer to the sensor device pointed by 434 * tree and look for the zone that refer to the sensor device pointed by
@@ -382,9 +453,8 @@ thermal_zone_of_add_sensor(struct device_node *zone,
382 * check the return value with help of IS_ERR() helper. 453 * check the return value with help of IS_ERR() helper.
383 */ 454 */
384struct thermal_zone_device * 455struct thermal_zone_device *
385thermal_zone_of_sensor_register(struct device *dev, int sensor_id, 456thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data,
386 void *data, int (*get_temp)(void *, long *), 457 const struct thermal_zone_of_device_ops *ops)
387 int (*get_trend)(void *, long *))
388{ 458{
389 struct device_node *np, *child, *sensor_np; 459 struct device_node *np, *child, *sensor_np;
390 struct thermal_zone_device *tzd = ERR_PTR(-ENODEV); 460 struct thermal_zone_device *tzd = ERR_PTR(-ENODEV);
@@ -426,9 +496,7 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id,
426 496
427 if (sensor_specs.np == sensor_np && id == sensor_id) { 497 if (sensor_specs.np == sensor_np && id == sensor_id) {
428 tzd = thermal_zone_of_add_sensor(child, sensor_np, 498 tzd = thermal_zone_of_add_sensor(child, sensor_np,
429 data, 499 data, ops);
430 get_temp,
431 get_trend);
432 of_node_put(sensor_specs.np); 500 of_node_put(sensor_specs.np);
433 of_node_put(child); 501 of_node_put(child);
434 goto exit; 502 goto exit;
@@ -475,9 +543,9 @@ void thermal_zone_of_sensor_unregister(struct device *dev,
475 mutex_lock(&tzd->lock); 543 mutex_lock(&tzd->lock);
476 tzd->ops->get_temp = NULL; 544 tzd->ops->get_temp = NULL;
477 tzd->ops->get_trend = NULL; 545 tzd->ops->get_trend = NULL;
546 tzd->ops->set_emul_temp = NULL;
478 547
479 tz->get_temp = NULL; 548 tz->ops = NULL;
480 tz->get_trend = NULL;
481 tz->sensor_data = NULL; 549 tz->sensor_data = NULL;
482 mutex_unlock(&tzd->lock); 550 mutex_unlock(&tzd->lock);
483} 551}
@@ -501,7 +569,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister);
501 */ 569 */
502static int thermal_of_populate_bind_params(struct device_node *np, 570static int thermal_of_populate_bind_params(struct device_node *np,
503 struct __thermal_bind_params *__tbp, 571 struct __thermal_bind_params *__tbp,
504 struct __thermal_trip *trips, 572 struct thermal_trip *trips,
505 int ntrips) 573 int ntrips)
506{ 574{
507 struct of_phandle_args cooling_spec; 575 struct of_phandle_args cooling_spec;
@@ -604,7 +672,7 @@ static int thermal_of_get_trip_type(struct device_node *np,
604 * Return: 0 on success, proper error code otherwise 672 * Return: 0 on success, proper error code otherwise
605 */ 673 */
606static int thermal_of_populate_trip(struct device_node *np, 674static int thermal_of_populate_trip(struct device_node *np,
607 struct __thermal_trip *trip) 675 struct thermal_trip *trip)
608{ 676{
609 int prop; 677 int prop;
610 int ret; 678 int ret;
diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
new file mode 100644
index 000000000000..1bcddfc60e91
--- /dev/null
+++ b/drivers/thermal/rockchip_thermal.c
@@ -0,0 +1,693 @@
1/*
2 * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 */
13
14#include <linux/clk.h>
15#include <linux/delay.h>
16#include <linux/interrupt.h>
17#include <linux/io.h>
18#include <linux/module.h>
19#include <linux/of.h>
20#include <linux/of_address.h>
21#include <linux/of_irq.h>
22#include <linux/platform_device.h>
23#include <linux/reset.h>
24#include <linux/thermal.h>
25
26/**
27 * If the temperature over a period of time High,
28 * the resulting TSHUT gave CRU module,let it reset the entire chip,
29 * or via GPIO give PMIC.
30 */
31enum tshut_mode {
32 TSHUT_MODE_CRU = 0,
33 TSHUT_MODE_GPIO,
34};
35
36/**
37 * the system Temperature Sensors tshut(tshut) polarity
38 * the bit 8 is tshut polarity.
39 * 0: low active, 1: high active
40 */
41enum tshut_polarity {
42 TSHUT_LOW_ACTIVE = 0,
43 TSHUT_HIGH_ACTIVE,
44};
45
46/**
47 * The system has three Temperature Sensors. channel 0 is reserved,
48 * channel 1 is for CPU, and channel 2 is for GPU.
49 */
50enum sensor_id {
51 SENSOR_CPU = 1,
52 SENSOR_GPU,
53};
54
55struct rockchip_tsadc_chip {
56 /* The hardware-controlled tshut property */
57 long tshut_temp;
58 enum tshut_mode tshut_mode;
59 enum tshut_polarity tshut_polarity;
60
61 /* Chip-wide methods */
62 void (*initialize)(void __iomem *reg, enum tshut_polarity p);
63 void (*irq_ack)(void __iomem *reg);
64 void (*control)(void __iomem *reg, bool on);
65
66 /* Per-sensor methods */
67 int (*get_temp)(int chn, void __iomem *reg, long *temp);
68 void (*set_tshut_temp)(int chn, void __iomem *reg, long temp);
69 void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m);
70};
71
72struct rockchip_thermal_sensor {
73 struct rockchip_thermal_data *thermal;
74 struct thermal_zone_device *tzd;
75 enum sensor_id id;
76};
77
78#define NUM_SENSORS 2 /* Ignore unused sensor 0 */
79
80struct rockchip_thermal_data {
81 const struct rockchip_tsadc_chip *chip;
82 struct platform_device *pdev;
83 struct reset_control *reset;
84
85 struct rockchip_thermal_sensor sensors[NUM_SENSORS];
86
87 struct clk *clk;
88 struct clk *pclk;
89
90 void __iomem *regs;
91
92 long tshut_temp;
93 enum tshut_mode tshut_mode;
94 enum tshut_polarity tshut_polarity;
95};
96
97/* TSADC V2 Sensor info define: */
98#define TSADCV2_AUTO_CON 0x04
99#define TSADCV2_INT_EN 0x08
100#define TSADCV2_INT_PD 0x0c
101#define TSADCV2_DATA(chn) (0x20 + (chn) * 0x04)
102#define TSADCV2_COMP_SHUT(chn) (0x40 + (chn) * 0x04)
103#define TSADCV2_HIGHT_INT_DEBOUNCE 0x60
104#define TSADCV2_HIGHT_TSHUT_DEBOUNCE 0x64
105#define TSADCV2_AUTO_PERIOD 0x68
106#define TSADCV2_AUTO_PERIOD_HT 0x6c
107
108#define TSADCV2_AUTO_EN BIT(0)
109#define TSADCV2_AUTO_DISABLE ~BIT(0)
110#define TSADCV2_AUTO_SRC_EN(chn) BIT(4 + (chn))
111#define TSADCV2_AUTO_TSHUT_POLARITY_HIGH BIT(8)
112#define TSADCV2_AUTO_TSHUT_POLARITY_LOW ~BIT(8)
113
114#define TSADCV2_INT_SRC_EN(chn) BIT(chn)
115#define TSADCV2_SHUT_2GPIO_SRC_EN(chn) BIT(4 + (chn))
116#define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (chn))
117
118#define TSADCV2_INT_PD_CLEAR ~BIT(8)
119
120#define TSADCV2_DATA_MASK 0xfff
121#define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT 4
122#define TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT 4
123#define TSADCV2_AUTO_PERIOD_TIME 250 /* msec */
124#define TSADCV2_AUTO_PERIOD_HT_TIME 50 /* msec */
125
126struct tsadc_table {
127 unsigned long code;
128 long temp;
129};
130
131static const struct tsadc_table v2_code_table[] = {
132 {TSADCV2_DATA_MASK, -40000},
133 {3800, -40000},
134 {3792, -35000},
135 {3783, -30000},
136 {3774, -25000},
137 {3765, -20000},
138 {3756, -15000},
139 {3747, -10000},
140 {3737, -5000},
141 {3728, 0},
142 {3718, 5000},
143 {3708, 10000},
144 {3698, 15000},
145 {3688, 20000},
146 {3678, 25000},
147 {3667, 30000},
148 {3656, 35000},
149 {3645, 40000},
150 {3634, 45000},
151 {3623, 50000},
152 {3611, 55000},
153 {3600, 60000},
154 {3588, 65000},
155 {3575, 70000},
156 {3563, 75000},
157 {3550, 80000},
158 {3537, 85000},
159 {3524, 90000},
160 {3510, 95000},
161 {3496, 100000},
162 {3482, 105000},
163 {3467, 110000},
164 {3452, 115000},
165 {3437, 120000},
166 {3421, 125000},
167 {0, 125000},
168};
169
170static u32 rk_tsadcv2_temp_to_code(long temp)
171{
172 int high, low, mid;
173
174 low = 0;
175 high = ARRAY_SIZE(v2_code_table) - 1;
176 mid = (high + low) / 2;
177
178 if (temp < v2_code_table[low].temp || temp > v2_code_table[high].temp)
179 return 0;
180
181 while (low <= high) {
182 if (temp == v2_code_table[mid].temp)
183 return v2_code_table[mid].code;
184 else if (temp < v2_code_table[mid].temp)
185 high = mid - 1;
186 else
187 low = mid + 1;
188 mid = (low + high) / 2;
189 }
190
191 return 0;
192}
193
194static long rk_tsadcv2_code_to_temp(u32 code)
195{
196 int high, low, mid;
197
198 low = 0;
199 high = ARRAY_SIZE(v2_code_table) - 1;
200 mid = (high + low) / 2;
201
202 if (code > v2_code_table[low].code || code < v2_code_table[high].code)
203 return 125000; /* No code available, return max temperature */
204
205 while (low <= high) {
206 if (code >= v2_code_table[mid].code && code <
207 v2_code_table[mid - 1].code)
208 return v2_code_table[mid].temp;
209 else if (code < v2_code_table[mid].code)
210 low = mid + 1;
211 else
212 high = mid - 1;
213 mid = (low + high) / 2;
214 }
215
216 return 125000;
217}
218
219/**
220 * rk_tsadcv2_initialize - initialize TASDC Controller
221 * (1) Set TSADCV2_AUTO_PERIOD, configure the interleave between
222 * every two accessing of TSADC in normal operation.
223 * (2) Set TSADCV2_AUTO_PERIOD_HT, configure the interleave between
224 * every two accessing of TSADC after the temperature is higher
225 * than COM_SHUT or COM_INT.
226 * (3) Set TSADCV2_HIGH_INT_DEBOUNCE and TSADC_HIGHT_TSHUT_DEBOUNCE,
227 * if the temperature is higher than COMP_INT or COMP_SHUT for
228 * "debounce" times, TSADC controller will generate interrupt or TSHUT.
229 */
230static void rk_tsadcv2_initialize(void __iomem *regs,
231 enum tshut_polarity tshut_polarity)
232{
233 if (tshut_polarity == TSHUT_HIGH_ACTIVE)
234 writel_relaxed(0 | (TSADCV2_AUTO_TSHUT_POLARITY_HIGH),
235 regs + TSADCV2_AUTO_CON);
236 else
237 writel_relaxed(0 | (TSADCV2_AUTO_TSHUT_POLARITY_LOW),
238 regs + TSADCV2_AUTO_CON);
239
240 writel_relaxed(TSADCV2_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD);
241 writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT,
242 regs + TSADCV2_HIGHT_INT_DEBOUNCE);
243 writel_relaxed(TSADCV2_AUTO_PERIOD_HT_TIME,
244 regs + TSADCV2_AUTO_PERIOD_HT);
245 writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT,
246 regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
247}
248
249static void rk_tsadcv2_irq_ack(void __iomem *regs)
250{
251 u32 val;
252
253 val = readl_relaxed(regs + TSADCV2_INT_PD);
254 writel_relaxed(val & TSADCV2_INT_PD_CLEAR, regs + TSADCV2_INT_PD);
255}
256
257static void rk_tsadcv2_control(void __iomem *regs, bool enable)
258{
259 u32 val;
260
261 val = readl_relaxed(regs + TSADCV2_AUTO_CON);
262 if (enable)
263 val |= TSADCV2_AUTO_EN;
264 else
265 val &= ~TSADCV2_AUTO_EN;
266
267 writel_relaxed(val, regs + TSADCV2_AUTO_CON);
268}
269
270static int rk_tsadcv2_get_temp(int chn, void __iomem *regs, long *temp)
271{
272 u32 val;
273
274 /* the A/D value of the channel last conversion need some time */
275 val = readl_relaxed(regs + TSADCV2_DATA(chn));
276 if (val == 0)
277 return -EAGAIN;
278
279 *temp = rk_tsadcv2_code_to_temp(val);
280
281 return 0;
282}
283
284static void rk_tsadcv2_tshut_temp(int chn, void __iomem *regs, long temp)
285{
286 u32 tshut_value, val;
287
288 tshut_value = rk_tsadcv2_temp_to_code(temp);
289 writel_relaxed(tshut_value, regs + TSADCV2_COMP_SHUT(chn));
290
291 /* TSHUT will be valid */
292 val = readl_relaxed(regs + TSADCV2_AUTO_CON);
293 writel_relaxed(val | TSADCV2_AUTO_SRC_EN(chn), regs + TSADCV2_AUTO_CON);
294}
295
296static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs,
297 enum tshut_mode mode)
298{
299 u32 val;
300
301 val = readl_relaxed(regs + TSADCV2_INT_EN);
302 if (mode == TSHUT_MODE_GPIO) {
303 val &= ~TSADCV2_SHUT_2CRU_SRC_EN(chn);
304 val |= TSADCV2_SHUT_2GPIO_SRC_EN(chn);
305 } else {
306 val &= ~TSADCV2_SHUT_2GPIO_SRC_EN(chn);
307 val |= TSADCV2_SHUT_2CRU_SRC_EN(chn);
308 }
309
310 writel_relaxed(val, regs + TSADCV2_INT_EN);
311}
312
313static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
314 .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */
315 .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
316 .tshut_temp = 95000,
317
318 .initialize = rk_tsadcv2_initialize,
319 .irq_ack = rk_tsadcv2_irq_ack,
320 .control = rk_tsadcv2_control,
321 .get_temp = rk_tsadcv2_get_temp,
322 .set_tshut_temp = rk_tsadcv2_tshut_temp,
323 .set_tshut_mode = rk_tsadcv2_tshut_mode,
324};
325
326static const struct of_device_id of_rockchip_thermal_match[] = {
327 {
328 .compatible = "rockchip,rk3288-tsadc",
329 .data = (void *)&rk3288_tsadc_data,
330 },
331 { /* end */ },
332};
333MODULE_DEVICE_TABLE(of, of_rockchip_thermal_match);
334
335static void
336rockchip_thermal_toggle_sensor(struct rockchip_thermal_sensor *sensor, bool on)
337{
338 struct thermal_zone_device *tzd = sensor->tzd;
339
340 tzd->ops->set_mode(tzd,
341 on ? THERMAL_DEVICE_ENABLED : THERMAL_DEVICE_DISABLED);
342}
343
344static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
345{
346 struct rockchip_thermal_data *thermal = dev;
347 int i;
348
349 dev_dbg(&thermal->pdev->dev, "thermal alarm\n");
350
351 thermal->chip->irq_ack(thermal->regs);
352
353 for (i = 0; i < ARRAY_SIZE(thermal->sensors); i++)
354 thermal_zone_device_update(thermal->sensors[i].tzd);
355
356 return IRQ_HANDLED;
357}
358
359static int rockchip_thermal_get_temp(void *_sensor, long *out_temp)
360{
361 struct rockchip_thermal_sensor *sensor = _sensor;
362 struct rockchip_thermal_data *thermal = sensor->thermal;
363 const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip;
364 int retval;
365
366 retval = tsadc->get_temp(sensor->id, thermal->regs, out_temp);
367 dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %ld, retval: %d\n",
368 sensor->id, *out_temp, retval);
369
370 return retval;
371}
372
373static const struct thermal_zone_of_device_ops rockchip_of_thermal_ops = {
374 .get_temp = rockchip_thermal_get_temp,
375};
376
377static int rockchip_configure_from_dt(struct device *dev,
378 struct device_node *np,
379 struct rockchip_thermal_data *thermal)
380{
381 u32 shut_temp, tshut_mode, tshut_polarity;
382
383 if (of_property_read_u32(np, "rockchip,hw-tshut-temp", &shut_temp)) {
384 dev_warn(dev,
385 "Missing tshut temp property, using default %ld\n",
386 thermal->chip->tshut_temp);
387 thermal->tshut_temp = thermal->chip->tshut_temp;
388 } else {
389 thermal->tshut_temp = shut_temp;
390 }
391
392 if (thermal->tshut_temp > INT_MAX) {
393 dev_err(dev, "Invalid tshut temperature specified: %ld\n",
394 thermal->tshut_temp);
395 return -ERANGE;
396 }
397
398 if (of_property_read_u32(np, "rockchip,hw-tshut-mode", &tshut_mode)) {
399 dev_warn(dev,
400 "Missing tshut mode property, using default (%s)\n",
401 thermal->chip->tshut_mode == TSHUT_MODE_GPIO ?
402 "gpio" : "cru");
403 thermal->tshut_mode = thermal->chip->tshut_mode;
404 } else {
405 thermal->tshut_mode = tshut_mode;
406 }
407
408 if (thermal->tshut_mode > 1) {
409 dev_err(dev, "Invalid tshut mode specified: %d\n",
410 thermal->tshut_mode);
411 return -EINVAL;
412 }
413
414 if (of_property_read_u32(np, "rockchip,hw-tshut-polarity",
415 &tshut_polarity)) {
416 dev_warn(dev,
417 "Missing tshut-polarity property, using default (%s)\n",
418 thermal->chip->tshut_polarity == TSHUT_LOW_ACTIVE ?
419 "low" : "high");
420 thermal->tshut_polarity = thermal->chip->tshut_polarity;
421 } else {
422 thermal->tshut_polarity = tshut_polarity;
423 }
424
425 if (thermal->tshut_polarity > 1) {
426 dev_err(dev, "Invalid tshut-polarity specified: %d\n",
427 thermal->tshut_polarity);
428 return -EINVAL;
429 }
430
431 return 0;
432}
433
434static int
435rockchip_thermal_register_sensor(struct platform_device *pdev,
436 struct rockchip_thermal_data *thermal,
437 struct rockchip_thermal_sensor *sensor,
438 enum sensor_id id)
439{
440 const struct rockchip_tsadc_chip *tsadc = thermal->chip;
441 int error;
442
443 tsadc->set_tshut_mode(id, thermal->regs, thermal->tshut_mode);
444 tsadc->set_tshut_temp(id, thermal->regs, thermal->tshut_temp);
445
446 sensor->thermal = thermal;
447 sensor->id = id;
448 sensor->tzd = thermal_zone_of_sensor_register(&pdev->dev, id, sensor,
449 &rockchip_of_thermal_ops);
450 if (IS_ERR(sensor->tzd)) {
451 error = PTR_ERR(sensor->tzd);
452 dev_err(&pdev->dev, "failed to register sensor %d: %d\n",
453 id, error);
454 return error;
455 }
456
457 return 0;
458}
459
460/*
461 * Reset TSADC Controller, reset all tsadc registers.
462 */
463static void rockchip_thermal_reset_controller(struct reset_control *reset)
464{
465 reset_control_assert(reset);
466 usleep_range(10, 20);
467 reset_control_deassert(reset);
468}
469
470static int rockchip_thermal_probe(struct platform_device *pdev)
471{
472 struct device_node *np = pdev->dev.of_node;
473 struct rockchip_thermal_data *thermal;
474 const struct of_device_id *match;
475 struct resource *res;
476 int irq;
477 int i;
478 int error;
479
480 match = of_match_node(of_rockchip_thermal_match, np);
481 if (!match)
482 return -ENXIO;
483
484 irq = platform_get_irq(pdev, 0);
485 if (irq < 0) {
486 dev_err(&pdev->dev, "no irq resource?\n");
487 return -EINVAL;
488 }
489
490 thermal = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_thermal_data),
491 GFP_KERNEL);
492 if (!thermal)
493 return -ENOMEM;
494
495 thermal->pdev = pdev;
496
497 thermal->chip = (const struct rockchip_tsadc_chip *)match->data;
498 if (!thermal->chip)
499 return -EINVAL;
500
501 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
502 thermal->regs = devm_ioremap_resource(&pdev->dev, res);
503 if (IS_ERR(thermal->regs))
504 return PTR_ERR(thermal->regs);
505
506 thermal->reset = devm_reset_control_get(&pdev->dev, "tsadc-apb");
507 if (IS_ERR(thermal->reset)) {
508 error = PTR_ERR(thermal->reset);
509 dev_err(&pdev->dev, "failed to get tsadc reset: %d\n", error);
510 return error;
511 }
512
513 thermal->clk = devm_clk_get(&pdev->dev, "tsadc");
514 if (IS_ERR(thermal->clk)) {
515 error = PTR_ERR(thermal->clk);
516 dev_err(&pdev->dev, "failed to get tsadc clock: %d\n", error);
517 return error;
518 }
519
520 thermal->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
521 if (IS_ERR(thermal->pclk)) {
522 error = PTR_ERR(thermal->clk);
523 dev_err(&pdev->dev, "failed to get apb_pclk clock: %d\n",
524 error);
525 return error;
526 }
527
528 error = clk_prepare_enable(thermal->clk);
529 if (error) {
530 dev_err(&pdev->dev, "failed to enable converter clock: %d\n",
531 error);
532 return error;
533 }
534
535 error = clk_prepare_enable(thermal->pclk);
536 if (error) {
537 dev_err(&pdev->dev, "failed to enable pclk: %d\n", error);
538 goto err_disable_clk;
539 }
540
541 rockchip_thermal_reset_controller(thermal->reset);
542
543 error = rockchip_configure_from_dt(&pdev->dev, np, thermal);
544 if (error) {
545 dev_err(&pdev->dev, "failed to parse device tree data: %d\n",
546 error);
547 goto err_disable_pclk;
548 }
549
550 thermal->chip->initialize(thermal->regs, thermal->tshut_polarity);
551
552 error = rockchip_thermal_register_sensor(pdev, thermal,
553 &thermal->sensors[0],
554 SENSOR_CPU);
555 if (error) {
556 dev_err(&pdev->dev,
557 "failed to register CPU thermal sensor: %d\n", error);
558 goto err_disable_pclk;
559 }
560
561 error = rockchip_thermal_register_sensor(pdev, thermal,
562 &thermal->sensors[1],
563 SENSOR_GPU);
564 if (error) {
565 dev_err(&pdev->dev,
566 "failed to register GPU thermal sensor: %d\n", error);
567 goto err_unregister_cpu_sensor;
568 }
569
570 error = devm_request_threaded_irq(&pdev->dev, irq, NULL,
571 &rockchip_thermal_alarm_irq_thread,
572 IRQF_ONESHOT,
573 "rockchip_thermal", thermal);
574 if (error) {
575 dev_err(&pdev->dev,
576 "failed to request tsadc irq: %d\n", error);
577 goto err_unregister_gpu_sensor;
578 }
579
580 thermal->chip->control(thermal->regs, true);
581
582 for (i = 0; i < ARRAY_SIZE(thermal->sensors); i++)
583 rockchip_thermal_toggle_sensor(&thermal->sensors[i], true);
584
585 platform_set_drvdata(pdev, thermal);
586
587 return 0;
588
589err_unregister_gpu_sensor:
590 thermal_zone_of_sensor_unregister(&pdev->dev, thermal->sensors[1].tzd);
591err_unregister_cpu_sensor:
592 thermal_zone_of_sensor_unregister(&pdev->dev, thermal->sensors[0].tzd);
593err_disable_pclk:
594 clk_disable_unprepare(thermal->pclk);
595err_disable_clk:
596 clk_disable_unprepare(thermal->clk);
597
598 return error;
599}
600
601static int rockchip_thermal_remove(struct platform_device *pdev)
602{
603 struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev);
604 int i;
605
606 for (i = 0; i < ARRAY_SIZE(thermal->sensors); i++) {
607 struct rockchip_thermal_sensor *sensor = &thermal->sensors[i];
608
609 rockchip_thermal_toggle_sensor(sensor, false);
610 thermal_zone_of_sensor_unregister(&pdev->dev, sensor->tzd);
611 }
612
613 thermal->chip->control(thermal->regs, false);
614
615 clk_disable_unprepare(thermal->pclk);
616 clk_disable_unprepare(thermal->clk);
617
618 return 0;
619}
620
621static int __maybe_unused rockchip_thermal_suspend(struct device *dev)
622{
623 struct platform_device *pdev = to_platform_device(dev);
624 struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev);
625 int i;
626
627 for (i = 0; i < ARRAY_SIZE(thermal->sensors); i++)
628 rockchip_thermal_toggle_sensor(&thermal->sensors[i], false);
629
630 thermal->chip->control(thermal->regs, false);
631
632 clk_disable(thermal->pclk);
633 clk_disable(thermal->clk);
634
635 return 0;
636}
637
638static int __maybe_unused rockchip_thermal_resume(struct device *dev)
639{
640 struct platform_device *pdev = to_platform_device(dev);
641 struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev);
642 int i;
643 int error;
644
645 error = clk_enable(thermal->clk);
646 if (error)
647 return error;
648
649 error = clk_enable(thermal->pclk);
650 if (error)
651 return error;
652
653 rockchip_thermal_reset_controller(thermal->reset);
654
655 thermal->chip->initialize(thermal->regs, thermal->tshut_polarity);
656
657 for (i = 0; i < ARRAY_SIZE(thermal->sensors); i++) {
658 enum sensor_id id = thermal->sensors[i].id;
659
660 thermal->chip->set_tshut_mode(id, thermal->regs,
661 thermal->tshut_mode);
662 thermal->chip->set_tshut_temp(id, thermal->regs,
663 thermal->tshut_temp);
664 }
665
666 thermal->chip->control(thermal->regs, true);
667
668 for (i = 0; i < ARRAY_SIZE(thermal->sensors); i++)
669 rockchip_thermal_toggle_sensor(&thermal->sensors[i], true);
670
671 return 0;
672}
673
674static SIMPLE_DEV_PM_OPS(rockchip_thermal_pm_ops,
675 rockchip_thermal_suspend, rockchip_thermal_resume);
676
677static struct platform_driver rockchip_thermal_driver = {
678 .driver = {
679 .name = "rockchip-thermal",
680 .owner = THIS_MODULE,
681 .pm = &rockchip_thermal_pm_ops,
682 .of_match_table = of_rockchip_thermal_match,
683 },
684 .probe = rockchip_thermal_probe,
685 .remove = rockchip_thermal_remove,
686};
687
688module_platform_driver(rockchip_thermal_driver);
689
690MODULE_DESCRIPTION("ROCKCHIP THERMAL Driver");
691MODULE_AUTHOR("Rockchip, Inc.");
692MODULE_LICENSE("GPL v2");
693MODULE_ALIAS("platform:rockchip-thermal");
diff --git a/drivers/thermal/samsung/exynos_thermal_common.h b/drivers/thermal/samsung/exynos_thermal_common.h
index 158f5aa8dc5d..cd4471925cdd 100644
--- a/drivers/thermal/samsung/exynos_thermal_common.h
+++ b/drivers/thermal/samsung/exynos_thermal_common.h
@@ -27,7 +27,6 @@
27#define SENSOR_NAME_LEN 16 27#define SENSOR_NAME_LEN 16
28#define MAX_TRIP_COUNT 8 28#define MAX_TRIP_COUNT 8
29#define MAX_COOLING_DEVICE 4 29#define MAX_COOLING_DEVICE 4
30#define MAX_TRIMINFO_CTRL_REG 2
31 30
32#define ACTIVE_INTERVAL 500 31#define ACTIVE_INTERVAL 500
33#define IDLE_INTERVAL 10000 32#define IDLE_INTERVAL 10000
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 1e7d0736e862..d44d91d681d4 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -33,7 +33,87 @@
33 33
34#include "exynos_thermal_common.h" 34#include "exynos_thermal_common.h"
35#include "exynos_tmu.h" 35#include "exynos_tmu.h"
36#include "exynos_tmu_data.h" 36
37/* Exynos generic registers */
38#define EXYNOS_TMU_REG_TRIMINFO 0x0
39#define EXYNOS_TMU_REG_CONTROL 0x20
40#define EXYNOS_TMU_REG_STATUS 0x28
41#define EXYNOS_TMU_REG_CURRENT_TEMP 0x40
42#define EXYNOS_TMU_REG_INTEN 0x70
43#define EXYNOS_TMU_REG_INTSTAT 0x74
44#define EXYNOS_TMU_REG_INTCLEAR 0x78
45
46#define EXYNOS_TMU_TEMP_MASK 0xff
47#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
48#define EXYNOS_TMU_REF_VOLTAGE_MASK 0x1f
49#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK 0xf
50#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT 8
51#define EXYNOS_TMU_CORE_EN_SHIFT 0
52
53/* Exynos3250 specific registers */
54#define EXYNOS_TMU_TRIMINFO_CON1 0x10
55
56/* Exynos4210 specific registers */
57#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP 0x44
58#define EXYNOS4210_TMU_REG_TRIG_LEVEL0 0x50
59
60/* Exynos5250, Exynos4412, Exynos3250 specific registers */
61#define EXYNOS_TMU_TRIMINFO_CON2 0x14
62#define EXYNOS_THD_TEMP_RISE 0x50
63#define EXYNOS_THD_TEMP_FALL 0x54
64#define EXYNOS_EMUL_CON 0x80
65
66#define EXYNOS_TRIMINFO_RELOAD_ENABLE 1
67#define EXYNOS_TRIMINFO_25_SHIFT 0
68#define EXYNOS_TRIMINFO_85_SHIFT 8
69#define EXYNOS_TMU_TRIP_MODE_SHIFT 13
70#define EXYNOS_TMU_TRIP_MODE_MASK 0x7
71#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT 12
72
73#define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
74#define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
75#define EXYNOS_TMU_INTEN_RISE2_SHIFT 8
76#define EXYNOS_TMU_INTEN_RISE3_SHIFT 12
77#define EXYNOS_TMU_INTEN_FALL0_SHIFT 16
78
79#define EXYNOS_EMUL_TIME 0x57F0
80#define EXYNOS_EMUL_TIME_MASK 0xffff
81#define EXYNOS_EMUL_TIME_SHIFT 16
82#define EXYNOS_EMUL_DATA_SHIFT 8
83#define EXYNOS_EMUL_DATA_MASK 0xFF
84#define EXYNOS_EMUL_ENABLE 0x1
85
86/* Exynos5260 specific */
87#define EXYNOS5260_TMU_REG_INTEN 0xC0
88#define EXYNOS5260_TMU_REG_INTSTAT 0xC4
89#define EXYNOS5260_TMU_REG_INTCLEAR 0xC8
90#define EXYNOS5260_EMUL_CON 0x100
91
92/* Exynos4412 specific */
93#define EXYNOS4412_MUX_ADDR_VALUE 6
94#define EXYNOS4412_MUX_ADDR_SHIFT 20
95
96/*exynos5440 specific registers*/
97#define EXYNOS5440_TMU_S0_7_TRIM 0x000
98#define EXYNOS5440_TMU_S0_7_CTRL 0x020
99#define EXYNOS5440_TMU_S0_7_DEBUG 0x040
100#define EXYNOS5440_TMU_S0_7_TEMP 0x0f0
101#define EXYNOS5440_TMU_S0_7_TH0 0x110
102#define EXYNOS5440_TMU_S0_7_TH1 0x130
103#define EXYNOS5440_TMU_S0_7_TH2 0x150
104#define EXYNOS5440_TMU_S0_7_IRQEN 0x210
105#define EXYNOS5440_TMU_S0_7_IRQ 0x230
106/* exynos5440 common registers */
107#define EXYNOS5440_TMU_IRQ_STATUS 0x000
108#define EXYNOS5440_TMU_PMIN 0x004
109
110#define EXYNOS5440_TMU_INTEN_RISE0_SHIFT 0
111#define EXYNOS5440_TMU_INTEN_RISE1_SHIFT 1
112#define EXYNOS5440_TMU_INTEN_RISE2_SHIFT 2
113#define EXYNOS5440_TMU_INTEN_RISE3_SHIFT 3
114#define EXYNOS5440_TMU_INTEN_FALL0_SHIFT 4
115#define EXYNOS5440_TMU_TH_RISE4_SHIFT 24
116#define EXYNOS5440_EFUSE_SWAP_OFFSET 8
37 117
38/** 118/**
39 * struct exynos_tmu_data : A structure to hold the private data of the TMU 119 * struct exynos_tmu_data : A structure to hold the private data of the TMU
@@ -52,6 +132,11 @@
52 * @temp_error2: fused value of the second point trim. 132 * @temp_error2: fused value of the second point trim.
53 * @regulator: pointer to the TMU regulator structure. 133 * @regulator: pointer to the TMU regulator structure.
54 * @reg_conf: pointer to structure to register with core thermal. 134 * @reg_conf: pointer to structure to register with core thermal.
135 * @tmu_initialize: SoC specific TMU initialization method
136 * @tmu_control: SoC specific TMU control method
137 * @tmu_read: SoC specific TMU temperature read method
138 * @tmu_set_emulation: SoC specific TMU emulation setting method
139 * @tmu_clear_irqs: SoC specific TMU interrupts clearing method
55 */ 140 */
56struct exynos_tmu_data { 141struct exynos_tmu_data {
57 int id; 142 int id;
@@ -66,6 +151,12 @@ struct exynos_tmu_data {
66 u8 temp_error1, temp_error2; 151 u8 temp_error1, temp_error2;
67 struct regulator *regulator; 152 struct regulator *regulator;
68 struct thermal_sensor_conf *reg_conf; 153 struct thermal_sensor_conf *reg_conf;
154 int (*tmu_initialize)(struct platform_device *pdev);
155 void (*tmu_control)(struct platform_device *pdev, bool on);
156 int (*tmu_read)(struct exynos_tmu_data *data);
157 void (*tmu_set_emulation)(struct exynos_tmu_data *data,
158 unsigned long temp);
159 void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
69}; 160};
70 161
71/* 162/*
@@ -122,83 +213,10 @@ static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code)
122 return temp; 213 return temp;
123} 214}
124 215
125static void exynos_tmu_clear_irqs(struct exynos_tmu_data *data) 216static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info)
126{
127 const struct exynos_tmu_registers *reg = data->pdata->registers;
128 unsigned int val_irq;
129
130 val_irq = readl(data->base + reg->tmu_intstat);
131 /*
132 * Clear the interrupts. Please note that the documentation for
133 * Exynos3250, Exynos4412, Exynos5250 and Exynos5260 incorrectly
134 * states that INTCLEAR register has a different placing of bits
135 * responsible for FALL IRQs than INTSTAT register. Exynos5420
136 * and Exynos5440 documentation is correct (Exynos4210 doesn't
137 * support FALL IRQs at all).
138 */
139 writel(val_irq, data->base + reg->tmu_intclear);
140}
141
142static int exynos_tmu_initialize(struct platform_device *pdev)
143{ 217{
144 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
145 struct exynos_tmu_platform_data *pdata = data->pdata; 218 struct exynos_tmu_platform_data *pdata = data->pdata;
146 const struct exynos_tmu_registers *reg = pdata->registers;
147 unsigned int status, trim_info = 0, con, ctrl;
148 unsigned int rising_threshold = 0, falling_threshold = 0;
149 int ret = 0, threshold_code, i;
150
151 mutex_lock(&data->lock);
152 clk_enable(data->clk);
153 if (!IS_ERR(data->clk_sec))
154 clk_enable(data->clk_sec);
155 219
156 if (TMU_SUPPORTS(pdata, READY_STATUS)) {
157 status = readb(data->base + reg->tmu_status);
158 if (!status) {
159 ret = -EBUSY;
160 goto out;
161 }
162 }
163
164 if (TMU_SUPPORTS(pdata, TRIM_RELOAD)) {
165 for (i = 0; i < reg->triminfo_ctrl_count; i++) {
166 if (pdata->triminfo_reload[i]) {
167 ctrl = readl(data->base +
168 reg->triminfo_ctrl[i]);
169 ctrl |= pdata->triminfo_reload[i];
170 writel(ctrl, data->base +
171 reg->triminfo_ctrl[i]);
172 }
173 }
174 }
175
176 /* Save trimming info in order to perform calibration */
177 if (data->soc == SOC_ARCH_EXYNOS5440) {
178 /*
179 * For exynos5440 soc triminfo value is swapped between TMU0 and
180 * TMU2, so the below logic is needed.
181 */
182 switch (data->id) {
183 case 0:
184 trim_info = readl(data->base +
185 EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
186 break;
187 case 1:
188 trim_info = readl(data->base + reg->triminfo_data);
189 break;
190 case 2:
191 trim_info = readl(data->base -
192 EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
193 }
194 } else {
195 /* On exynos5420 the triminfo register is in the shared space */
196 if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO)
197 trim_info = readl(data->base_second +
198 reg->triminfo_data);
199 else
200 trim_info = readl(data->base + reg->triminfo_data);
201 }
202 data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK; 220 data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
203 data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) & 221 data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) &
204 EXYNOS_TMU_TEMP_MASK); 222 EXYNOS_TMU_TEMP_MASK);
@@ -212,69 +230,37 @@ static int exynos_tmu_initialize(struct platform_device *pdev)
212 data->temp_error2 = 230 data->temp_error2 =
213 (pdata->efuse_value >> EXYNOS_TRIMINFO_85_SHIFT) & 231 (pdata->efuse_value >> EXYNOS_TRIMINFO_85_SHIFT) &
214 EXYNOS_TMU_TEMP_MASK; 232 EXYNOS_TMU_TEMP_MASK;
233}
215 234
216 rising_threshold = readl(data->base + reg->threshold_th0); 235static u32 get_th_reg(struct exynos_tmu_data *data, u32 threshold, bool falling)
236{
237 struct exynos_tmu_platform_data *pdata = data->pdata;
238 int i;
217 239
218 if (data->soc == SOC_ARCH_EXYNOS4210) { 240 for (i = 0; i < pdata->non_hw_trigger_levels; i++) {
219 /* Write temperature code for threshold */ 241 u8 temp = pdata->trigger_levels[i];
220 threshold_code = temp_to_code(data, pdata->threshold);
221 writeb(threshold_code,
222 data->base + reg->threshold_temp);
223 for (i = 0; i < pdata->non_hw_trigger_levels; i++)
224 writeb(pdata->trigger_levels[i], data->base +
225 reg->threshold_th0 + i * sizeof(reg->threshold_th0));
226 242
227 exynos_tmu_clear_irqs(data); 243 if (falling)
228 } else { 244 temp -= pdata->threshold_falling;
229 /* Write temperature code for rising and falling threshold */ 245 else
230 for (i = 0; i < pdata->non_hw_trigger_levels; i++) { 246 threshold &= ~(0xff << 8 * i);
231 threshold_code = temp_to_code(data,
232 pdata->trigger_levels[i]);
233 rising_threshold &= ~(0xff << 8 * i);
234 rising_threshold |= threshold_code << 8 * i;
235 if (pdata->threshold_falling) {
236 threshold_code = temp_to_code(data,
237 pdata->trigger_levels[i] -
238 pdata->threshold_falling);
239 falling_threshold |= threshold_code << 8 * i;
240 }
241 }
242 247
243 writel(rising_threshold, 248 threshold |= temp_to_code(data, temp) << 8 * i;
244 data->base + reg->threshold_th0);
245 writel(falling_threshold,
246 data->base + reg->threshold_th1);
247
248 exynos_tmu_clear_irqs(data);
249
250 /* if last threshold limit is also present */
251 i = pdata->max_trigger_level - 1;
252 if (pdata->trigger_levels[i] &&
253 (pdata->trigger_type[i] == HW_TRIP)) {
254 threshold_code = temp_to_code(data,
255 pdata->trigger_levels[i]);
256 if (i == EXYNOS_MAX_TRIGGER_PER_REG - 1) {
257 /* 1-4 level to be assigned in th0 reg */
258 rising_threshold &= ~(0xff << 8 * i);
259 rising_threshold |= threshold_code << 8 * i;
260 writel(rising_threshold,
261 data->base + reg->threshold_th0);
262 } else if (i == EXYNOS_MAX_TRIGGER_PER_REG) {
263 /* 5th level to be assigned in th2 reg */
264 rising_threshold =
265 threshold_code << reg->threshold_th3_l0_shift;
266 writel(rising_threshold,
267 data->base + reg->threshold_th2);
268 }
269 con = readl(data->base + reg->tmu_ctrl);
270 con |= (1 << reg->therm_trip_en_shift);
271 writel(con, data->base + reg->tmu_ctrl);
272 }
273 } 249 }
274 /*Clear the PMIN in the common TMU register*/ 250
275 if (reg->tmu_pmin && !data->id) 251 return threshold;
276 writel(0, data->base_second + reg->tmu_pmin); 252}
277out: 253
254static int exynos_tmu_initialize(struct platform_device *pdev)
255{
256 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
257 int ret;
258
259 mutex_lock(&data->lock);
260 clk_enable(data->clk);
261 if (!IS_ERR(data->clk_sec))
262 clk_enable(data->clk_sec);
263 ret = data->tmu_initialize(pdev);
278 clk_disable(data->clk); 264 clk_disable(data->clk);
279 mutex_unlock(&data->lock); 265 mutex_unlock(&data->lock);
280 if (!IS_ERR(data->clk_sec)) 266 if (!IS_ERR(data->clk_sec))
@@ -283,20 +269,13 @@ out:
283 return ret; 269 return ret;
284} 270}
285 271
286static void exynos_tmu_control(struct platform_device *pdev, bool on) 272static u32 get_con_reg(struct exynos_tmu_data *data, u32 con)
287{ 273{
288 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
289 struct exynos_tmu_platform_data *pdata = data->pdata; 274 struct exynos_tmu_platform_data *pdata = data->pdata;
290 const struct exynos_tmu_registers *reg = pdata->registers;
291 unsigned int con, interrupt_en;
292 275
293 mutex_lock(&data->lock); 276 if (data->soc == SOC_ARCH_EXYNOS4412 ||
294 clk_enable(data->clk); 277 data->soc == SOC_ARCH_EXYNOS3250)
295 278 con |= (EXYNOS4412_MUX_ADDR_VALUE << EXYNOS4412_MUX_ADDR_SHIFT);
296 con = readl(data->base + reg->tmu_ctrl);
297
298 if (pdata->test_mux)
299 con |= (pdata->test_mux << reg->test_mux_addr_shift);
300 279
301 con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK << EXYNOS_TMU_REF_VOLTAGE_SHIFT); 280 con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK << EXYNOS_TMU_REF_VOLTAGE_SHIFT);
302 con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT; 281 con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
@@ -305,95 +284,287 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
305 con |= (pdata->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT); 284 con |= (pdata->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT);
306 285
307 if (pdata->noise_cancel_mode) { 286 if (pdata->noise_cancel_mode) {
308 con &= ~(reg->therm_trip_mode_mask << 287 con &= ~(EXYNOS_TMU_TRIP_MODE_MASK << EXYNOS_TMU_TRIP_MODE_SHIFT);
309 reg->therm_trip_mode_shift); 288 con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);
310 con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
311 } 289 }
312 290
313 if (on) { 291 return con;
314 con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT); 292}
315 interrupt_en = 293
316 pdata->trigger_enable[3] << reg->inten_rise3_shift | 294static void exynos_tmu_control(struct platform_device *pdev, bool on)
317 pdata->trigger_enable[2] << reg->inten_rise2_shift | 295{
318 pdata->trigger_enable[1] << reg->inten_rise1_shift | 296 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
319 pdata->trigger_enable[0] << reg->inten_rise0_shift;
320 if (TMU_SUPPORTS(pdata, FALLING_TRIP))
321 interrupt_en |=
322 interrupt_en << reg->inten_fall0_shift;
323 } else {
324 con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
325 interrupt_en = 0; /* Disable all interrupts */
326 }
327 writel(interrupt_en, data->base + reg->tmu_inten);
328 writel(con, data->base + reg->tmu_ctrl);
329 297
298 mutex_lock(&data->lock);
299 clk_enable(data->clk);
300 data->tmu_control(pdev, on);
330 clk_disable(data->clk); 301 clk_disable(data->clk);
331 mutex_unlock(&data->lock); 302 mutex_unlock(&data->lock);
332} 303}
333 304
334static int exynos_tmu_read(struct exynos_tmu_data *data) 305static int exynos4210_tmu_initialize(struct platform_device *pdev)
335{ 306{
307 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
336 struct exynos_tmu_platform_data *pdata = data->pdata; 308 struct exynos_tmu_platform_data *pdata = data->pdata;
337 const struct exynos_tmu_registers *reg = pdata->registers; 309 unsigned int status;
338 u8 temp_code; 310 int ret = 0, threshold_code, i;
339 int temp;
340 311
341 mutex_lock(&data->lock); 312 status = readb(data->base + EXYNOS_TMU_REG_STATUS);
342 clk_enable(data->clk); 313 if (!status) {
314 ret = -EBUSY;
315 goto out;
316 }
343 317
344 temp_code = readb(data->base + reg->tmu_cur_temp); 318 sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO));
345 319
346 if (data->soc == SOC_ARCH_EXYNOS4210) 320 /* Write temperature code for threshold */
347 /* temp_code should range between 75 and 175 */ 321 threshold_code = temp_to_code(data, pdata->threshold);
348 if (temp_code < 75 || temp_code > 175) { 322 writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
349 temp = -ENODATA; 323
350 goto out; 324 for (i = 0; i < pdata->non_hw_trigger_levels; i++)
325 writeb(pdata->trigger_levels[i], data->base +
326 EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
327
328 data->tmu_clear_irqs(data);
329out:
330 return ret;
331}
332
333static int exynos4412_tmu_initialize(struct platform_device *pdev)
334{
335 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
336 struct exynos_tmu_platform_data *pdata = data->pdata;
337 unsigned int status, trim_info, con, ctrl, rising_threshold;
338 int ret = 0, threshold_code, i;
339
340 status = readb(data->base + EXYNOS_TMU_REG_STATUS);
341 if (!status) {
342 ret = -EBUSY;
343 goto out;
344 }
345
346 if (data->soc == SOC_ARCH_EXYNOS3250 ||
347 data->soc == SOC_ARCH_EXYNOS4412 ||
348 data->soc == SOC_ARCH_EXYNOS5250) {
349 if (data->soc == SOC_ARCH_EXYNOS3250) {
350 ctrl = readl(data->base + EXYNOS_TMU_TRIMINFO_CON1);
351 ctrl |= EXYNOS_TRIMINFO_RELOAD_ENABLE;
352 writel(ctrl, data->base + EXYNOS_TMU_TRIMINFO_CON1);
351 } 353 }
354 ctrl = readl(data->base + EXYNOS_TMU_TRIMINFO_CON2);
355 ctrl |= EXYNOS_TRIMINFO_RELOAD_ENABLE;
356 writel(ctrl, data->base + EXYNOS_TMU_TRIMINFO_CON2);
357 }
352 358
353 temp = code_to_temp(data, temp_code); 359 /* On exynos5420 the triminfo register is in the shared space */
360 if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO)
361 trim_info = readl(data->base_second + EXYNOS_TMU_REG_TRIMINFO);
362 else
363 trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
364
365 sanitize_temp_error(data, trim_info);
366
367 /* Write temperature code for rising and falling threshold */
368 rising_threshold = readl(data->base + EXYNOS_THD_TEMP_RISE);
369 rising_threshold = get_th_reg(data, rising_threshold, false);
370 writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
371 writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL);
372
373 data->tmu_clear_irqs(data);
374
375 /* if last threshold limit is also present */
376 i = pdata->max_trigger_level - 1;
377 if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) {
378 threshold_code = temp_to_code(data, pdata->trigger_levels[i]);
379 /* 1-4 level to be assigned in th0 reg */
380 rising_threshold &= ~(0xff << 8 * i);
381 rising_threshold |= threshold_code << 8 * i;
382 writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
383 con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
384 con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
385 writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
386 }
354out: 387out:
355 clk_disable(data->clk); 388 return ret;
356 mutex_unlock(&data->lock); 389}
357 390
358 return temp; 391static int exynos5440_tmu_initialize(struct platform_device *pdev)
392{
393 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
394 struct exynos_tmu_platform_data *pdata = data->pdata;
395 unsigned int trim_info = 0, con, rising_threshold;
396 int ret = 0, threshold_code, i;
397
398 /*
399 * For exynos5440 soc triminfo value is swapped between TMU0 and
400 * TMU2, so the below logic is needed.
401 */
402 switch (data->id) {
403 case 0:
404 trim_info = readl(data->base + EXYNOS5440_EFUSE_SWAP_OFFSET +
405 EXYNOS5440_TMU_S0_7_TRIM);
406 break;
407 case 1:
408 trim_info = readl(data->base + EXYNOS5440_TMU_S0_7_TRIM);
409 break;
410 case 2:
411 trim_info = readl(data->base - EXYNOS5440_EFUSE_SWAP_OFFSET +
412 EXYNOS5440_TMU_S0_7_TRIM);
413 }
414 sanitize_temp_error(data, trim_info);
415
416 /* Write temperature code for rising and falling threshold */
417 rising_threshold = readl(data->base + EXYNOS5440_TMU_S0_7_TH0);
418 rising_threshold = get_th_reg(data, rising_threshold, false);
419 writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH0);
420 writel(0, data->base + EXYNOS5440_TMU_S0_7_TH1);
421
422 data->tmu_clear_irqs(data);
423
424 /* if last threshold limit is also present */
425 i = pdata->max_trigger_level - 1;
426 if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) {
427 threshold_code = temp_to_code(data, pdata->trigger_levels[i]);
428 /* 5th level to be assigned in th2 reg */
429 rising_threshold =
430 threshold_code << EXYNOS5440_TMU_TH_RISE4_SHIFT;
431 writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH2);
432 con = readl(data->base + EXYNOS5440_TMU_S0_7_CTRL);
433 con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
434 writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL);
435 }
436 /* Clear the PMIN in the common TMU register */
437 if (!data->id)
438 writel(0, data->base_second + EXYNOS5440_TMU_PMIN);
439 return ret;
359} 440}
360 441
361#ifdef CONFIG_THERMAL_EMULATION 442static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
362static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
363{ 443{
364 struct exynos_tmu_data *data = drv_data; 444 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
365 struct exynos_tmu_platform_data *pdata = data->pdata; 445 struct exynos_tmu_platform_data *pdata = data->pdata;
366 const struct exynos_tmu_registers *reg = pdata->registers; 446 unsigned int con, interrupt_en;
367 unsigned int val;
368 int ret = -EINVAL;
369 447
370 if (!TMU_SUPPORTS(pdata, EMULATION)) 448 con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
371 goto out;
372 449
373 if (temp && temp < MCELSIUS) 450 if (on) {
374 goto out; 451 con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
452 interrupt_en =
453 pdata->trigger_enable[3] << EXYNOS_TMU_INTEN_RISE3_SHIFT |
454 pdata->trigger_enable[2] << EXYNOS_TMU_INTEN_RISE2_SHIFT |
455 pdata->trigger_enable[1] << EXYNOS_TMU_INTEN_RISE1_SHIFT |
456 pdata->trigger_enable[0] << EXYNOS_TMU_INTEN_RISE0_SHIFT;
457 if (data->soc != SOC_ARCH_EXYNOS4210)
458 interrupt_en |=
459 interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
460 } else {
461 con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
462 interrupt_en = 0; /* Disable all interrupts */
463 }
464 writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
465 writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
466}
467
468static void exynos5440_tmu_control(struct platform_device *pdev, bool on)
469{
470 struct exynos_tmu_data *data = platform_get_drvdata(pdev);
471 struct exynos_tmu_platform_data *pdata = data->pdata;
472 unsigned int con, interrupt_en;
473
474 con = get_con_reg(data, readl(data->base + EXYNOS5440_TMU_S0_7_CTRL));
475
476 if (on) {
477 con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
478 interrupt_en =
479 pdata->trigger_enable[3] << EXYNOS5440_TMU_INTEN_RISE3_SHIFT |
480 pdata->trigger_enable[2] << EXYNOS5440_TMU_INTEN_RISE2_SHIFT |
481 pdata->trigger_enable[1] << EXYNOS5440_TMU_INTEN_RISE1_SHIFT |
482 pdata->trigger_enable[0] << EXYNOS5440_TMU_INTEN_RISE0_SHIFT;
483 interrupt_en |= interrupt_en << EXYNOS5440_TMU_INTEN_FALL0_SHIFT;
484 } else {
485 con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
486 interrupt_en = 0; /* Disable all interrupts */
487 }
488 writel(interrupt_en, data->base + EXYNOS5440_TMU_S0_7_IRQEN);
489 writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL);
490}
491
492static int exynos_tmu_read(struct exynos_tmu_data *data)
493{
494 int ret;
375 495
376 mutex_lock(&data->lock); 496 mutex_lock(&data->lock);
377 clk_enable(data->clk); 497 clk_enable(data->clk);
498 ret = data->tmu_read(data);
499 if (ret >= 0)
500 ret = code_to_temp(data, ret);
501 clk_disable(data->clk);
502 mutex_unlock(&data->lock);
378 503
379 val = readl(data->base + reg->emul_con); 504 return ret;
505}
380 506
507#ifdef CONFIG_THERMAL_EMULATION
508static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val,
509 unsigned long temp)
510{
381 if (temp) { 511 if (temp) {
382 temp /= MCELSIUS; 512 temp /= MCELSIUS;
383 513
384 if (TMU_SUPPORTS(pdata, EMUL_TIME)) { 514 if (data->soc != SOC_ARCH_EXYNOS5440) {
385 val &= ~(EXYNOS_EMUL_TIME_MASK << reg->emul_time_shift); 515 val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT);
386 val |= (EXYNOS_EMUL_TIME << reg->emul_time_shift); 516 val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT);
387 } 517 }
388 val &= ~(EXYNOS_EMUL_DATA_MASK << reg->emul_temp_shift); 518 val &= ~(EXYNOS_EMUL_DATA_MASK << EXYNOS_EMUL_DATA_SHIFT);
389 val |= (temp_to_code(data, temp) << reg->emul_temp_shift) | 519 val |= (temp_to_code(data, temp) << EXYNOS_EMUL_DATA_SHIFT) |
390 EXYNOS_EMUL_ENABLE; 520 EXYNOS_EMUL_ENABLE;
391 } else { 521 } else {
392 val &= ~EXYNOS_EMUL_ENABLE; 522 val &= ~EXYNOS_EMUL_ENABLE;
393 } 523 }
394 524
395 writel(val, data->base + reg->emul_con); 525 return val;
526}
527
528static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
529 unsigned long temp)
530{
531 unsigned int val;
532 u32 emul_con;
533
534 if (data->soc == SOC_ARCH_EXYNOS5260)
535 emul_con = EXYNOS5260_EMUL_CON;
536 else
537 emul_con = EXYNOS_EMUL_CON;
538
539 val = readl(data->base + emul_con);
540 val = get_emul_con_reg(data, val, temp);
541 writel(val, data->base + emul_con);
542}
543
544static void exynos5440_tmu_set_emulation(struct exynos_tmu_data *data,
545 unsigned long temp)
546{
547 unsigned int val;
548
549 val = readl(data->base + EXYNOS5440_TMU_S0_7_DEBUG);
550 val = get_emul_con_reg(data, val, temp);
551 writel(val, data->base + EXYNOS5440_TMU_S0_7_DEBUG);
552}
553
554static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
555{
556 struct exynos_tmu_data *data = drv_data;
557 int ret = -EINVAL;
558
559 if (data->soc == SOC_ARCH_EXYNOS4210)
560 goto out;
396 561
562 if (temp && temp < MCELSIUS)
563 goto out;
564
565 mutex_lock(&data->lock);
566 clk_enable(data->clk);
567 data->tmu_set_emulation(data, temp);
397 clk_disable(data->clk); 568 clk_disable(data->clk);
398 mutex_unlock(&data->lock); 569 mutex_unlock(&data->lock);
399 return 0; 570 return 0;
@@ -401,23 +572,41 @@ out:
401 return ret; 572 return ret;
402} 573}
403#else 574#else
575#define exynos4412_tmu_set_emulation NULL
576#define exynos5440_tmu_set_emulation NULL
404static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp) 577static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
405 { return -EINVAL; } 578 { return -EINVAL; }
406#endif/*CONFIG_THERMAL_EMULATION*/ 579#endif/*CONFIG_THERMAL_EMULATION*/
407 580
581static int exynos4210_tmu_read(struct exynos_tmu_data *data)
582{
583 int ret = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
584
585 /* "temp_code" should range between 75 and 175 */
586 return (ret < 75 || ret > 175) ? -ENODATA : ret;
587}
588
589static int exynos4412_tmu_read(struct exynos_tmu_data *data)
590{
591 return readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
592}
593
594static int exynos5440_tmu_read(struct exynos_tmu_data *data)
595{
596 return readb(data->base + EXYNOS5440_TMU_S0_7_TEMP);
597}
598
408static void exynos_tmu_work(struct work_struct *work) 599static void exynos_tmu_work(struct work_struct *work)
409{ 600{
410 struct exynos_tmu_data *data = container_of(work, 601 struct exynos_tmu_data *data = container_of(work,
411 struct exynos_tmu_data, irq_work); 602 struct exynos_tmu_data, irq_work);
412 struct exynos_tmu_platform_data *pdata = data->pdata;
413 const struct exynos_tmu_registers *reg = pdata->registers;
414 unsigned int val_type; 603 unsigned int val_type;
415 604
416 if (!IS_ERR(data->clk_sec)) 605 if (!IS_ERR(data->clk_sec))
417 clk_enable(data->clk_sec); 606 clk_enable(data->clk_sec);
418 /* Find which sensor generated this interrupt */ 607 /* Find which sensor generated this interrupt */
419 if (reg->tmu_irqstatus) { 608 if (data->soc == SOC_ARCH_EXYNOS5440) {
420 val_type = readl(data->base_second + reg->tmu_irqstatus); 609 val_type = readl(data->base_second + EXYNOS5440_TMU_IRQ_STATUS);
421 if (!((val_type >> data->id) & 0x1)) 610 if (!((val_type >> data->id) & 0x1))
422 goto out; 611 goto out;
423 } 612 }
@@ -429,7 +618,7 @@ static void exynos_tmu_work(struct work_struct *work)
429 clk_enable(data->clk); 618 clk_enable(data->clk);
430 619
431 /* TODO: take action based on particular interrupt */ 620 /* TODO: take action based on particular interrupt */
432 exynos_tmu_clear_irqs(data); 621 data->tmu_clear_irqs(data);
433 622
434 clk_disable(data->clk); 623 clk_disable(data->clk);
435 mutex_unlock(&data->lock); 624 mutex_unlock(&data->lock);
@@ -437,6 +626,40 @@ out:
437 enable_irq(data->irq); 626 enable_irq(data->irq);
438} 627}
439 628
629static void exynos4210_tmu_clear_irqs(struct exynos_tmu_data *data)
630{
631 unsigned int val_irq;
632 u32 tmu_intstat, tmu_intclear;
633
634 if (data->soc == SOC_ARCH_EXYNOS5260) {
635 tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT;
636 tmu_intclear = EXYNOS5260_TMU_REG_INTCLEAR;
637 } else {
638 tmu_intstat = EXYNOS_TMU_REG_INTSTAT;
639 tmu_intclear = EXYNOS_TMU_REG_INTCLEAR;
640 }
641
642 val_irq = readl(data->base + tmu_intstat);
643 /*
644 * Clear the interrupts. Please note that the documentation for
645 * Exynos3250, Exynos4412, Exynos5250 and Exynos5260 incorrectly
646 * states that INTCLEAR register has a different placing of bits
647 * responsible for FALL IRQs than INTSTAT register. Exynos5420
648 * and Exynos5440 documentation is correct (Exynos4210 doesn't
649 * support FALL IRQs at all).
650 */
651 writel(val_irq, data->base + tmu_intclear);
652}
653
654static void exynos5440_tmu_clear_irqs(struct exynos_tmu_data *data)
655{
656 unsigned int val_irq;
657
658 val_irq = readl(data->base + EXYNOS5440_TMU_S0_7_IRQ);
659 /* clear the interrupts */
660 writel(val_irq, data->base + EXYNOS5440_TMU_S0_7_IRQ);
661}
662
440static irqreturn_t exynos_tmu_irq(int irq, void *id) 663static irqreturn_t exynos_tmu_irq(int irq, void *id)
441{ 664{
442 struct exynos_tmu_data *data = id; 665 struct exynos_tmu_data *data = id;
@@ -450,35 +673,35 @@ static irqreturn_t exynos_tmu_irq(int irq, void *id)
450static const struct of_device_id exynos_tmu_match[] = { 673static const struct of_device_id exynos_tmu_match[] = {
451 { 674 {
452 .compatible = "samsung,exynos3250-tmu", 675 .compatible = "samsung,exynos3250-tmu",
453 .data = (void *)EXYNOS3250_TMU_DRV_DATA, 676 .data = &exynos3250_default_tmu_data,
454 }, 677 },
455 { 678 {
456 .compatible = "samsung,exynos4210-tmu", 679 .compatible = "samsung,exynos4210-tmu",
457 .data = (void *)EXYNOS4210_TMU_DRV_DATA, 680 .data = &exynos4210_default_tmu_data,
458 }, 681 },
459 { 682 {
460 .compatible = "samsung,exynos4412-tmu", 683 .compatible = "samsung,exynos4412-tmu",
461 .data = (void *)EXYNOS4412_TMU_DRV_DATA, 684 .data = &exynos4412_default_tmu_data,
462 }, 685 },
463 { 686 {
464 .compatible = "samsung,exynos5250-tmu", 687 .compatible = "samsung,exynos5250-tmu",
465 .data = (void *)EXYNOS5250_TMU_DRV_DATA, 688 .data = &exynos5250_default_tmu_data,
466 }, 689 },
467 { 690 {
468 .compatible = "samsung,exynos5260-tmu", 691 .compatible = "samsung,exynos5260-tmu",
469 .data = (void *)EXYNOS5260_TMU_DRV_DATA, 692 .data = &exynos5260_default_tmu_data,
470 }, 693 },
471 { 694 {
472 .compatible = "samsung,exynos5420-tmu", 695 .compatible = "samsung,exynos5420-tmu",
473 .data = (void *)EXYNOS5420_TMU_DRV_DATA, 696 .data = &exynos5420_default_tmu_data,
474 }, 697 },
475 { 698 {
476 .compatible = "samsung,exynos5420-tmu-ext-triminfo", 699 .compatible = "samsung,exynos5420-tmu-ext-triminfo",
477 .data = (void *)EXYNOS5420_TMU_DRV_DATA, 700 .data = &exynos5420_default_tmu_data,
478 }, 701 },
479 { 702 {
480 .compatible = "samsung,exynos5440-tmu", 703 .compatible = "samsung,exynos5440-tmu",
481 .data = (void *)EXYNOS5440_TMU_DRV_DATA, 704 .data = &exynos5440_default_tmu_data,
482 }, 705 },
483 {}, 706 {},
484}; 707};
@@ -553,12 +776,47 @@ static int exynos_map_dt_data(struct platform_device *pdev)
553 dev_err(&pdev->dev, "No platform init data supplied.\n"); 776 dev_err(&pdev->dev, "No platform init data supplied.\n");
554 return -ENODEV; 777 return -ENODEV;
555 } 778 }
779
556 data->pdata = pdata; 780 data->pdata = pdata;
781 data->soc = pdata->type;
782
783 switch (data->soc) {
784 case SOC_ARCH_EXYNOS4210:
785 data->tmu_initialize = exynos4210_tmu_initialize;
786 data->tmu_control = exynos4210_tmu_control;
787 data->tmu_read = exynos4210_tmu_read;
788 data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
789 break;
790 case SOC_ARCH_EXYNOS3250:
791 case SOC_ARCH_EXYNOS4412:
792 case SOC_ARCH_EXYNOS5250:
793 case SOC_ARCH_EXYNOS5260:
794 case SOC_ARCH_EXYNOS5420:
795 case SOC_ARCH_EXYNOS5420_TRIMINFO:
796 data->tmu_initialize = exynos4412_tmu_initialize;
797 data->tmu_control = exynos4210_tmu_control;
798 data->tmu_read = exynos4412_tmu_read;
799 data->tmu_set_emulation = exynos4412_tmu_set_emulation;
800 data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
801 break;
802 case SOC_ARCH_EXYNOS5440:
803 data->tmu_initialize = exynos5440_tmu_initialize;
804 data->tmu_control = exynos5440_tmu_control;
805 data->tmu_read = exynos5440_tmu_read;
806 data->tmu_set_emulation = exynos5440_tmu_set_emulation;
807 data->tmu_clear_irqs = exynos5440_tmu_clear_irqs;
808 break;
809 default:
810 dev_err(&pdev->dev, "Platform not supported\n");
811 return -EINVAL;
812 }
813
557 /* 814 /*
558 * Check if the TMU shares some registers and then try to map the 815 * Check if the TMU shares some registers and then try to map the
559 * memory of common registers. 816 * memory of common registers.
560 */ 817 */
561 if (!TMU_SUPPORTS(pdata, ADDRESS_MULTIPLE)) 818 if (data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO &&
819 data->soc != SOC_ARCH_EXYNOS5440)
562 return 0; 820 return 0;
563 821
564 if (of_address_to_resource(pdev->dev.of_node, 1, &res)) { 822 if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
@@ -625,20 +883,6 @@ static int exynos_tmu_probe(struct platform_device *pdev)
625 goto err_clk_sec; 883 goto err_clk_sec;
626 } 884 }
627 885
628 if (pdata->type == SOC_ARCH_EXYNOS3250 ||
629 pdata->type == SOC_ARCH_EXYNOS4210 ||
630 pdata->type == SOC_ARCH_EXYNOS4412 ||
631 pdata->type == SOC_ARCH_EXYNOS5250 ||
632 pdata->type == SOC_ARCH_EXYNOS5260 ||
633 pdata->type == SOC_ARCH_EXYNOS5420_TRIMINFO ||
634 pdata->type == SOC_ARCH_EXYNOS5440)
635 data->soc = pdata->type;
636 else {
637 ret = -EINVAL;
638 dev_err(&pdev->dev, "Platform not supported\n");
639 goto err_clk;
640 }
641
642 ret = exynos_tmu_initialize(pdev); 886 ret = exynos_tmu_initialize(pdev);
643 if (ret) { 887 if (ret) {
644 dev_err(&pdev->dev, "Failed to initialize TMU\n"); 888 dev_err(&pdev->dev, "Failed to initialize TMU\n");
diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
index c58c7663a3fe..da3009bff6c4 100644
--- a/drivers/thermal/samsung/exynos_tmu.h
+++ b/drivers/thermal/samsung/exynos_tmu.h
@@ -40,115 +40,12 @@ enum soc_type {
40 SOC_ARCH_EXYNOS4412, 40 SOC_ARCH_EXYNOS4412,
41 SOC_ARCH_EXYNOS5250, 41 SOC_ARCH_EXYNOS5250,
42 SOC_ARCH_EXYNOS5260, 42 SOC_ARCH_EXYNOS5260,
43 SOC_ARCH_EXYNOS5420,
43 SOC_ARCH_EXYNOS5420_TRIMINFO, 44 SOC_ARCH_EXYNOS5420_TRIMINFO,
44 SOC_ARCH_EXYNOS5440, 45 SOC_ARCH_EXYNOS5440,
45}; 46};
46 47
47/** 48/**
48 * EXYNOS TMU supported features.
49 * TMU_SUPPORT_EMULATION - This features is used to set user defined
50 * temperature to the TMU controller.
51 * TMU_SUPPORT_MULTI_INST - This features denotes that the soc
52 * has many instances of TMU.
53 * TMU_SUPPORT_TRIM_RELOAD - This features shows that trimming can
54 * be reloaded.
55 * TMU_SUPPORT_FALLING_TRIP - This features shows that interrupt can
56 * be registered for falling trips also.
57 * TMU_SUPPORT_READY_STATUS - This feature tells that the TMU current
58 * state(active/idle) can be checked.
59 * TMU_SUPPORT_EMUL_TIME - This features allows to set next temp emulation
60 * sample time.
61 * TMU_SUPPORT_ADDRESS_MULTIPLE - This feature tells that the different TMU
62 * sensors shares some common registers.
63 * TMU_SUPPORT - macro to compare the above features with the supplied.
64 */
65#define TMU_SUPPORT_EMULATION BIT(0)
66#define TMU_SUPPORT_MULTI_INST BIT(1)
67#define TMU_SUPPORT_TRIM_RELOAD BIT(2)
68#define TMU_SUPPORT_FALLING_TRIP BIT(3)
69#define TMU_SUPPORT_READY_STATUS BIT(4)
70#define TMU_SUPPORT_EMUL_TIME BIT(5)
71#define TMU_SUPPORT_ADDRESS_MULTIPLE BIT(6)
72
73#define TMU_SUPPORTS(a, b) (a->features & TMU_SUPPORT_ ## b)
74
75/**
76 * struct exynos_tmu_register - register descriptors to access registers and
77 * bitfields. The register validity, offsets and bitfield values may vary
78 * slightly across different exynos SOC's.
79 * @triminfo_data: register containing 2 pont trimming data
80 * @triminfo_ctrl: trim info controller register.
81 * @triminfo_ctrl_count: the number of trim info controller register.
82 * @tmu_ctrl: TMU main controller register.
83 * @test_mux_addr_shift: shift bits of test mux address.
84 * @therm_trip_mode_shift: shift bits of tripping mode in tmu_ctrl register.
85 * @therm_trip_mode_mask: mask bits of tripping mode in tmu_ctrl register.
86 * @therm_trip_en_shift: shift bits of tripping enable in tmu_ctrl register.
87 * @tmu_status: register drescribing the TMU status.
88 * @tmu_cur_temp: register containing the current temperature of the TMU.
89 * @threshold_temp: register containing the base threshold level.
90 * @threshold_th0: Register containing first set of rising levels.
91 * @threshold_th1: Register containing second set of rising levels.
92 * @threshold_th2: Register containing third set of rising levels.
93 * @threshold_th3_l0_shift: shift bits of level0 threshold temperature.
94 * @tmu_inten: register containing the different threshold interrupt
95 enable bits.
96 * @inten_rise0_shift: shift bits of rising 0 interrupt bits.
97 * @inten_rise1_shift: shift bits of rising 1 interrupt bits.
98 * @inten_rise2_shift: shift bits of rising 2 interrupt bits.
99 * @inten_rise3_shift: shift bits of rising 3 interrupt bits.
100 * @inten_fall0_shift: shift bits of falling 0 interrupt bits.
101 * @tmu_intstat: Register containing the interrupt status values.
102 * @tmu_intclear: Register for clearing the raised interrupt status.
103 * @emul_con: TMU emulation controller register.
104 * @emul_temp_shift: shift bits of emulation temperature.
105 * @emul_time_shift: shift bits of emulation time.
106 * @tmu_irqstatus: register to find which TMU generated interrupts.
107 * @tmu_pmin: register to get/set the Pmin value.
108 */
109struct exynos_tmu_registers {
110 u32 triminfo_data;
111
112 u32 triminfo_ctrl[MAX_TRIMINFO_CTRL_REG];
113 u32 triminfo_ctrl_count;
114
115 u32 tmu_ctrl;
116 u32 test_mux_addr_shift;
117 u32 therm_trip_mode_shift;
118 u32 therm_trip_mode_mask;
119 u32 therm_trip_en_shift;
120
121 u32 tmu_status;
122
123 u32 tmu_cur_temp;
124
125 u32 threshold_temp;
126
127 u32 threshold_th0;
128 u32 threshold_th1;
129 u32 threshold_th2;
130 u32 threshold_th3_l0_shift;
131
132 u32 tmu_inten;
133 u32 inten_rise0_shift;
134 u32 inten_rise1_shift;
135 u32 inten_rise2_shift;
136 u32 inten_rise3_shift;
137 u32 inten_fall0_shift;
138
139 u32 tmu_intstat;
140
141 u32 tmu_intclear;
142
143 u32 emul_con;
144 u32 emul_temp_shift;
145 u32 emul_time_shift;
146
147 u32 tmu_irqstatus;
148 u32 tmu_pmin;
149};
150
151/**
152 * struct exynos_tmu_platform_data 49 * struct exynos_tmu_platform_data
153 * @threshold: basic temperature for generating interrupt 50 * @threshold: basic temperature for generating interrupt
154 * 25 <= threshold <= 125 [unit: degree Celsius] 51 * 25 <= threshold <= 125 [unit: degree Celsius]
@@ -192,16 +89,10 @@ struct exynos_tmu_registers {
192 * @first_point_trim: temp value of the first point trimming 89 * @first_point_trim: temp value of the first point trimming
193 * @second_point_trim: temp value of the second point trimming 90 * @second_point_trim: temp value of the second point trimming
194 * @default_temp_offset: default temperature offset in case of no trimming 91 * @default_temp_offset: default temperature offset in case of no trimming
195 * @test_mux; information if SoC supports test MUX
196 * @triminfo_reload: reload value to read TRIMINFO register
197 * @cal_type: calibration type for temperature 92 * @cal_type: calibration type for temperature
198 * @freq_clip_table: Table representing frequency reduction percentage. 93 * @freq_clip_table: Table representing frequency reduction percentage.
199 * @freq_tab_count: Count of the above table as frequency reduction may 94 * @freq_tab_count: Count of the above table as frequency reduction may
200 * applicable to only some of the trigger levels. 95 * applicable to only some of the trigger levels.
201 * @registers: Pointer to structure containing all the TMU controller registers
202 * and bitfields shifts and masks.
203 * @features: a bitfield value indicating the features supported in SOC like
204 * emulation, multi instance etc
205 * 96 *
206 * This structure is required for configuration of exynos_tmu driver. 97 * This structure is required for configuration of exynos_tmu driver.
207 */ 98 */
@@ -223,15 +114,11 @@ struct exynos_tmu_platform_data {
223 u8 first_point_trim; 114 u8 first_point_trim;
224 u8 second_point_trim; 115 u8 second_point_trim;
225 u8 default_temp_offset; 116 u8 default_temp_offset;
226 u8 test_mux;
227 u8 triminfo_reload[MAX_TRIMINFO_CTRL_REG];
228 117
229 enum calibration_type cal_type; 118 enum calibration_type cal_type;
230 enum soc_type type; 119 enum soc_type type;
231 struct freq_clip_table freq_tab[4]; 120 struct freq_clip_table freq_tab[4];
232 unsigned int freq_tab_count; 121 unsigned int freq_tab_count;
233 const struct exynos_tmu_registers *registers;
234 unsigned int features;
235}; 122};
236 123
237/** 124/**
@@ -246,4 +133,12 @@ struct exynos_tmu_init_data {
246 struct exynos_tmu_platform_data tmu_data[]; 133 struct exynos_tmu_platform_data tmu_data[];
247}; 134};
248 135
136extern struct exynos_tmu_init_data const exynos3250_default_tmu_data;
137extern struct exynos_tmu_init_data const exynos4210_default_tmu_data;
138extern struct exynos_tmu_init_data const exynos4412_default_tmu_data;
139extern struct exynos_tmu_init_data const exynos5250_default_tmu_data;
140extern struct exynos_tmu_init_data const exynos5260_default_tmu_data;
141extern struct exynos_tmu_init_data const exynos5420_default_tmu_data;
142extern struct exynos_tmu_init_data const exynos5440_default_tmu_data;
143
249#endif /* _EXYNOS_TMU_H */ 144#endif /* _EXYNOS_TMU_H */
diff --git a/drivers/thermal/samsung/exynos_tmu_data.c b/drivers/thermal/samsung/exynos_tmu_data.c
index 1724f6cdaef8..b23910069f68 100644
--- a/drivers/thermal/samsung/exynos_tmu_data.c
+++ b/drivers/thermal/samsung/exynos_tmu_data.c
@@ -22,24 +22,6 @@
22 22
23#include "exynos_thermal_common.h" 23#include "exynos_thermal_common.h"
24#include "exynos_tmu.h" 24#include "exynos_tmu.h"
25#include "exynos_tmu_data.h"
26
27#if defined(CONFIG_CPU_EXYNOS4210)
28static const struct exynos_tmu_registers exynos4210_tmu_registers = {
29 .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
30 .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
31 .tmu_status = EXYNOS_TMU_REG_STATUS,
32 .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
33 .threshold_temp = EXYNOS4210_TMU_REG_THRESHOLD_TEMP,
34 .threshold_th0 = EXYNOS4210_TMU_REG_TRIG_LEVEL0,
35 .tmu_inten = EXYNOS_TMU_REG_INTEN,
36 .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
37 .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
38 .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
39 .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
40 .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
41 .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
42};
43 25
44struct exynos_tmu_init_data const exynos4210_default_tmu_data = { 26struct exynos_tmu_init_data const exynos4210_default_tmu_data = {
45 .tmu_data = { 27 .tmu_data = {
@@ -75,40 +57,10 @@ struct exynos_tmu_init_data const exynos4210_default_tmu_data = {
75 }, 57 },
76 .freq_tab_count = 2, 58 .freq_tab_count = 2,
77 .type = SOC_ARCH_EXYNOS4210, 59 .type = SOC_ARCH_EXYNOS4210,
78 .registers = &exynos4210_tmu_registers,
79 .features = TMU_SUPPORT_READY_STATUS,
80 }, 60 },
81 }, 61 },
82 .tmu_count = 1, 62 .tmu_count = 1,
83}; 63};
84#endif
85
86#if defined(CONFIG_SOC_EXYNOS3250)
87static const struct exynos_tmu_registers exynos3250_tmu_registers = {
88 .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
89 .triminfo_ctrl[0] = EXYNOS_TMU_TRIMINFO_CON1,
90 .triminfo_ctrl[1] = EXYNOS_TMU_TRIMINFO_CON2,
91 .triminfo_ctrl_count = 2,
92 .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
93 .test_mux_addr_shift = EXYNOS4412_MUX_ADDR_SHIFT,
94 .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
95 .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
96 .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
97 .tmu_status = EXYNOS_TMU_REG_STATUS,
98 .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
99 .threshold_th0 = EXYNOS_THD_TEMP_RISE,
100 .threshold_th1 = EXYNOS_THD_TEMP_FALL,
101 .tmu_inten = EXYNOS_TMU_REG_INTEN,
102 .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
103 .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
104 .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
105 .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
106 .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
107 .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
108 .emul_con = EXYNOS_EMUL_CON,
109 .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
110 .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
111};
112 64
113#define EXYNOS3250_TMU_DATA \ 65#define EXYNOS3250_TMU_DATA \
114 .threshold_falling = 10, \ 66 .threshold_falling = 10, \
@@ -144,54 +96,17 @@ static const struct exynos_tmu_registers exynos3250_tmu_registers = {
144 .freq_clip_max = 400 * 1000, \ 96 .freq_clip_max = 400 * 1000, \
145 .temp_level = 95, \ 97 .temp_level = 95, \
146 }, \ 98 }, \
147 .freq_tab_count = 2, \ 99 .freq_tab_count = 2
148 .triminfo_reload[0] = EXYNOS_TRIMINFO_RELOAD_ENABLE, \
149 .triminfo_reload[1] = EXYNOS_TRIMINFO_RELOAD_ENABLE, \
150 .registers = &exynos3250_tmu_registers, \
151 .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD | \
152 TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS | \
153 TMU_SUPPORT_EMUL_TIME)
154#endif
155 100
156#if defined(CONFIG_SOC_EXYNOS3250)
157struct exynos_tmu_init_data const exynos3250_default_tmu_data = { 101struct exynos_tmu_init_data const exynos3250_default_tmu_data = {
158 .tmu_data = { 102 .tmu_data = {
159 { 103 {
160 EXYNOS3250_TMU_DATA, 104 EXYNOS3250_TMU_DATA,
161 .type = SOC_ARCH_EXYNOS3250, 105 .type = SOC_ARCH_EXYNOS3250,
162 .test_mux = EXYNOS4412_MUX_ADDR_VALUE,
163 }, 106 },
164 }, 107 },
165 .tmu_count = 1, 108 .tmu_count = 1,
166}; 109};
167#endif
168
169#if defined(CONFIG_SOC_EXYNOS4412) || defined(CONFIG_SOC_EXYNOS5250)
170static const struct exynos_tmu_registers exynos4412_tmu_registers = {
171 .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
172 .triminfo_ctrl[0] = EXYNOS_TMU_TRIMINFO_CON2,
173 .triminfo_ctrl_count = 1,
174 .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
175 .test_mux_addr_shift = EXYNOS4412_MUX_ADDR_SHIFT,
176 .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
177 .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
178 .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
179 .tmu_status = EXYNOS_TMU_REG_STATUS,
180 .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
181 .threshold_th0 = EXYNOS_THD_TEMP_RISE,
182 .threshold_th1 = EXYNOS_THD_TEMP_FALL,
183 .tmu_inten = EXYNOS_TMU_REG_INTEN,
184 .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
185 .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
186 .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
187 .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
188 .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
189 .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
190 .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
191 .emul_con = EXYNOS_EMUL_CON,
192 .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
193 .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
194};
195 110
196#define EXYNOS4412_TMU_DATA \ 111#define EXYNOS4412_TMU_DATA \
197 .threshold_falling = 10, \ 112 .threshold_falling = 10, \
@@ -227,28 +142,18 @@ static const struct exynos_tmu_registers exynos4412_tmu_registers = {
227 .freq_clip_max = 400 * 1000, \ 142 .freq_clip_max = 400 * 1000, \
228 .temp_level = 95, \ 143 .temp_level = 95, \
229 }, \ 144 }, \
230 .freq_tab_count = 2, \ 145 .freq_tab_count = 2
231 .triminfo_reload[0] = EXYNOS_TRIMINFO_RELOAD_ENABLE, \
232 .registers = &exynos4412_tmu_registers, \
233 .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_TRIM_RELOAD | \
234 TMU_SUPPORT_FALLING_TRIP | TMU_SUPPORT_READY_STATUS | \
235 TMU_SUPPORT_EMUL_TIME)
236#endif
237 146
238#if defined(CONFIG_SOC_EXYNOS4412)
239struct exynos_tmu_init_data const exynos4412_default_tmu_data = { 147struct exynos_tmu_init_data const exynos4412_default_tmu_data = {
240 .tmu_data = { 148 .tmu_data = {
241 { 149 {
242 EXYNOS4412_TMU_DATA, 150 EXYNOS4412_TMU_DATA,
243 .type = SOC_ARCH_EXYNOS4412, 151 .type = SOC_ARCH_EXYNOS4412,
244 .test_mux = EXYNOS4412_MUX_ADDR_VALUE,
245 }, 152 },
246 }, 153 },
247 .tmu_count = 1, 154 .tmu_count = 1,
248}; 155};
249#endif
250 156
251#if defined(CONFIG_SOC_EXYNOS5250)
252struct exynos_tmu_init_data const exynos5250_default_tmu_data = { 157struct exynos_tmu_init_data const exynos5250_default_tmu_data = {
253 .tmu_data = { 158 .tmu_data = {
254 { 159 {
@@ -258,31 +163,6 @@ struct exynos_tmu_init_data const exynos5250_default_tmu_data = {
258 }, 163 },
259 .tmu_count = 1, 164 .tmu_count = 1,
260}; 165};
261#endif
262
263#if defined(CONFIG_SOC_EXYNOS5260)
264static const struct exynos_tmu_registers exynos5260_tmu_registers = {
265 .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
266 .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
267 .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
268 .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
269 .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
270 .tmu_status = EXYNOS_TMU_REG_STATUS,
271 .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
272 .threshold_th0 = EXYNOS_THD_TEMP_RISE,
273 .threshold_th1 = EXYNOS_THD_TEMP_FALL,
274 .tmu_inten = EXYNOS5260_TMU_REG_INTEN,
275 .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
276 .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
277 .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
278 .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
279 .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
280 .tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT,
281 .tmu_intclear = EXYNOS5260_TMU_REG_INTCLEAR,
282 .emul_con = EXYNOS5260_EMUL_CON,
283 .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
284 .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
285};
286 166
287#define __EXYNOS5260_TMU_DATA \ 167#define __EXYNOS5260_TMU_DATA \
288 .threshold_falling = 10, \ 168 .threshold_falling = 10, \
@@ -319,13 +199,10 @@ static const struct exynos_tmu_registers exynos5260_tmu_registers = {
319 .temp_level = 103, \ 199 .temp_level = 103, \
320 }, \ 200 }, \
321 .freq_tab_count = 2, \ 201 .freq_tab_count = 2, \
322 .registers = &exynos5260_tmu_registers, \
323 202
324#define EXYNOS5260_TMU_DATA \ 203#define EXYNOS5260_TMU_DATA \
325 __EXYNOS5260_TMU_DATA \ 204 __EXYNOS5260_TMU_DATA \
326 .type = SOC_ARCH_EXYNOS5260, \ 205 .type = SOC_ARCH_EXYNOS5260
327 .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP | \
328 TMU_SUPPORT_READY_STATUS | TMU_SUPPORT_EMUL_TIME)
329 206
330struct exynos_tmu_init_data const exynos5260_default_tmu_data = { 207struct exynos_tmu_init_data const exynos5260_default_tmu_data = {
331 .tmu_data = { 208 .tmu_data = {
@@ -337,82 +214,14 @@ struct exynos_tmu_init_data const exynos5260_default_tmu_data = {
337 }, 214 },
338 .tmu_count = 5, 215 .tmu_count = 5,
339}; 216};
340#endif
341
342#if defined(CONFIG_SOC_EXYNOS5420)
343static const struct exynos_tmu_registers exynos5420_tmu_registers = {
344 .triminfo_data = EXYNOS_TMU_REG_TRIMINFO,
345 .tmu_ctrl = EXYNOS_TMU_REG_CONTROL,
346 .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
347 .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
348 .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
349 .tmu_status = EXYNOS_TMU_REG_STATUS,
350 .tmu_cur_temp = EXYNOS_TMU_REG_CURRENT_TEMP,
351 .threshold_th0 = EXYNOS_THD_TEMP_RISE,
352 .threshold_th1 = EXYNOS_THD_TEMP_FALL,
353 .tmu_inten = EXYNOS_TMU_REG_INTEN,
354 .inten_rise0_shift = EXYNOS_TMU_INTEN_RISE0_SHIFT,
355 .inten_rise1_shift = EXYNOS_TMU_INTEN_RISE1_SHIFT,
356 .inten_rise2_shift = EXYNOS_TMU_INTEN_RISE2_SHIFT,
357 /* INTEN_RISE3 Not availble in exynos5420 */
358 .inten_rise3_shift = EXYNOS_TMU_INTEN_RISE3_SHIFT,
359 .inten_fall0_shift = EXYNOS_TMU_INTEN_FALL0_SHIFT,
360 .tmu_intstat = EXYNOS_TMU_REG_INTSTAT,
361 .tmu_intclear = EXYNOS_TMU_REG_INTCLEAR,
362 .emul_con = EXYNOS_EMUL_CON,
363 .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
364 .emul_time_shift = EXYNOS_EMUL_TIME_SHIFT,
365};
366
367#define __EXYNOS5420_TMU_DATA \
368 .threshold_falling = 10, \
369 .trigger_levels[0] = 85, \
370 .trigger_levels[1] = 103, \
371 .trigger_levels[2] = 110, \
372 .trigger_levels[3] = 120, \
373 .trigger_enable[0] = true, \
374 .trigger_enable[1] = true, \
375 .trigger_enable[2] = true, \
376 .trigger_enable[3] = false, \
377 .trigger_type[0] = THROTTLE_ACTIVE, \
378 .trigger_type[1] = THROTTLE_ACTIVE, \
379 .trigger_type[2] = SW_TRIP, \
380 .trigger_type[3] = HW_TRIP, \
381 .max_trigger_level = 4, \
382 .non_hw_trigger_levels = 3, \
383 .gain = 8, \
384 .reference_voltage = 16, \
385 .noise_cancel_mode = 4, \
386 .cal_type = TYPE_ONE_POINT_TRIMMING, \
387 .efuse_value = 55, \
388 .min_efuse_value = 40, \
389 .max_efuse_value = 100, \
390 .first_point_trim = 25, \
391 .second_point_trim = 85, \
392 .default_temp_offset = 50, \
393 .freq_tab[0] = { \
394 .freq_clip_max = 800 * 1000, \
395 .temp_level = 85, \
396 }, \
397 .freq_tab[1] = { \
398 .freq_clip_max = 200 * 1000, \
399 .temp_level = 103, \
400 }, \
401 .freq_tab_count = 2, \
402 .registers = &exynos5420_tmu_registers, \
403 217
404#define EXYNOS5420_TMU_DATA \ 218#define EXYNOS5420_TMU_DATA \
405 __EXYNOS5420_TMU_DATA \ 219 __EXYNOS5260_TMU_DATA \
406 .type = SOC_ARCH_EXYNOS5250, \ 220 .type = SOC_ARCH_EXYNOS5420
407 .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP | \
408 TMU_SUPPORT_READY_STATUS | TMU_SUPPORT_EMUL_TIME)
409 221
410#define EXYNOS5420_TMU_DATA_SHARED \ 222#define EXYNOS5420_TMU_DATA_SHARED \
411 __EXYNOS5420_TMU_DATA \ 223 __EXYNOS5260_TMU_DATA \
412 .type = SOC_ARCH_EXYNOS5420_TRIMINFO, \ 224 .type = SOC_ARCH_EXYNOS5420_TRIMINFO
413 .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP | \
414 TMU_SUPPORT_READY_STATUS | TMU_SUPPORT_EMUL_TIME | \
415 TMU_SUPPORT_ADDRESS_MULTIPLE)
416 225
417struct exynos_tmu_init_data const exynos5420_default_tmu_data = { 226struct exynos_tmu_init_data const exynos5420_default_tmu_data = {
418 .tmu_data = { 227 .tmu_data = {
@@ -424,34 +233,6 @@ struct exynos_tmu_init_data const exynos5420_default_tmu_data = {
424 }, 233 },
425 .tmu_count = 5, 234 .tmu_count = 5,
426}; 235};
427#endif
428
429#if defined(CONFIG_SOC_EXYNOS5440)
430static const struct exynos_tmu_registers exynos5440_tmu_registers = {
431 .triminfo_data = EXYNOS5440_TMU_S0_7_TRIM,
432 .tmu_ctrl = EXYNOS5440_TMU_S0_7_CTRL,
433 .therm_trip_mode_shift = EXYNOS_TMU_TRIP_MODE_SHIFT,
434 .therm_trip_mode_mask = EXYNOS_TMU_TRIP_MODE_MASK,
435 .therm_trip_en_shift = EXYNOS_TMU_THERM_TRIP_EN_SHIFT,
436 .tmu_status = EXYNOS5440_TMU_S0_7_STATUS,
437 .tmu_cur_temp = EXYNOS5440_TMU_S0_7_TEMP,
438 .threshold_th0 = EXYNOS5440_TMU_S0_7_TH0,
439 .threshold_th1 = EXYNOS5440_TMU_S0_7_TH1,
440 .threshold_th2 = EXYNOS5440_TMU_S0_7_TH2,
441 .threshold_th3_l0_shift = EXYNOS5440_TMU_TH_RISE4_SHIFT,
442 .tmu_inten = EXYNOS5440_TMU_S0_7_IRQEN,
443 .inten_rise0_shift = EXYNOS5440_TMU_INTEN_RISE0_SHIFT,
444 .inten_rise1_shift = EXYNOS5440_TMU_INTEN_RISE1_SHIFT,
445 .inten_rise2_shift = EXYNOS5440_TMU_INTEN_RISE2_SHIFT,
446 .inten_rise3_shift = EXYNOS5440_TMU_INTEN_RISE3_SHIFT,
447 .inten_fall0_shift = EXYNOS5440_TMU_INTEN_FALL0_SHIFT,
448 .tmu_intstat = EXYNOS5440_TMU_S0_7_IRQ,
449 .tmu_intclear = EXYNOS5440_TMU_S0_7_IRQ,
450 .tmu_irqstatus = EXYNOS5440_TMU_IRQ_STATUS,
451 .emul_con = EXYNOS5440_TMU_S0_7_DEBUG,
452 .emul_temp_shift = EXYNOS_EMUL_DATA_SHIFT,
453 .tmu_pmin = EXYNOS5440_TMU_PMIN,
454};
455 236
456#define EXYNOS5440_TMU_DATA \ 237#define EXYNOS5440_TMU_DATA \
457 .trigger_levels[0] = 100, \ 238 .trigger_levels[0] = 100, \
@@ -471,10 +252,7 @@ static const struct exynos_tmu_registers exynos5440_tmu_registers = {
471 .first_point_trim = 25, \ 252 .first_point_trim = 25, \
472 .second_point_trim = 70, \ 253 .second_point_trim = 70, \
473 .default_temp_offset = 25, \ 254 .default_temp_offset = 25, \
474 .type = SOC_ARCH_EXYNOS5440, \ 255 .type = SOC_ARCH_EXYNOS5440
475 .registers = &exynos5440_tmu_registers, \
476 .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP | \
477 TMU_SUPPORT_MULTI_INST | TMU_SUPPORT_ADDRESS_MULTIPLE),
478 256
479struct exynos_tmu_init_data const exynos5440_default_tmu_data = { 257struct exynos_tmu_init_data const exynos5440_default_tmu_data = {
480 .tmu_data = { 258 .tmu_data = {
@@ -484,4 +262,3 @@ struct exynos_tmu_init_data const exynos5440_default_tmu_data = {
484 }, 262 },
485 .tmu_count = 3, 263 .tmu_count = 3,
486}; 264};
487#endif
diff --git a/drivers/thermal/samsung/exynos_tmu_data.h b/drivers/thermal/samsung/exynos_tmu_data.h
deleted file mode 100644
index 63de598c9c2c..000000000000
--- a/drivers/thermal/samsung/exynos_tmu_data.h
+++ /dev/null
@@ -1,159 +0,0 @@
1/*
2 * exynos_tmu_data.h - Samsung EXYNOS tmu data header file
3 *
4 * Copyright (C) 2013 Samsung Electronics
5 * Amit Daniel Kachhap <amit.daniel@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#ifndef _EXYNOS_TMU_DATA_H
24#define _EXYNOS_TMU_DATA_H
25
26/* Exynos generic registers */
27#define EXYNOS_TMU_REG_TRIMINFO 0x0
28#define EXYNOS_TMU_REG_CONTROL 0x20
29#define EXYNOS_TMU_REG_STATUS 0x28
30#define EXYNOS_TMU_REG_CURRENT_TEMP 0x40
31#define EXYNOS_TMU_REG_INTEN 0x70
32#define EXYNOS_TMU_REG_INTSTAT 0x74
33#define EXYNOS_TMU_REG_INTCLEAR 0x78
34
35#define EXYNOS_TMU_TEMP_MASK 0xff
36#define EXYNOS_TMU_REF_VOLTAGE_SHIFT 24
37#define EXYNOS_TMU_REF_VOLTAGE_MASK 0x1f
38#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK 0xf
39#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT 8
40#define EXYNOS_TMU_CORE_EN_SHIFT 0
41
42/* Exynos3250 specific registers */
43#define EXYNOS_TMU_TRIMINFO_CON1 0x10
44
45/* Exynos4210 specific registers */
46#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP 0x44
47#define EXYNOS4210_TMU_REG_TRIG_LEVEL0 0x50
48
49/* Exynos5250, Exynos4412, Exynos3250 specific registers */
50#define EXYNOS_TMU_TRIMINFO_CON2 0x14
51#define EXYNOS_THD_TEMP_RISE 0x50
52#define EXYNOS_THD_TEMP_FALL 0x54
53#define EXYNOS_EMUL_CON 0x80
54
55#define EXYNOS_TRIMINFO_RELOAD_ENABLE 1
56#define EXYNOS_TRIMINFO_25_SHIFT 0
57#define EXYNOS_TRIMINFO_85_SHIFT 8
58#define EXYNOS_TMU_TRIP_MODE_SHIFT 13
59#define EXYNOS_TMU_TRIP_MODE_MASK 0x7
60#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT 12
61
62#define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
63#define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
64#define EXYNOS_TMU_INTEN_RISE2_SHIFT 8
65#define EXYNOS_TMU_INTEN_RISE3_SHIFT 12
66#define EXYNOS_TMU_INTEN_FALL0_SHIFT 16
67
68#define EXYNOS_EMUL_TIME 0x57F0
69#define EXYNOS_EMUL_TIME_MASK 0xffff
70#define EXYNOS_EMUL_TIME_SHIFT 16
71#define EXYNOS_EMUL_DATA_SHIFT 8
72#define EXYNOS_EMUL_DATA_MASK 0xFF
73#define EXYNOS_EMUL_ENABLE 0x1
74
75#define EXYNOS_MAX_TRIGGER_PER_REG 4
76
77/* Exynos5260 specific */
78#define EXYNOS5260_TMU_REG_INTEN 0xC0
79#define EXYNOS5260_TMU_REG_INTSTAT 0xC4
80#define EXYNOS5260_TMU_REG_INTCLEAR 0xC8
81#define EXYNOS5260_EMUL_CON 0x100
82
83/* Exynos4412 specific */
84#define EXYNOS4412_MUX_ADDR_VALUE 6
85#define EXYNOS4412_MUX_ADDR_SHIFT 20
86
87/*exynos5440 specific registers*/
88#define EXYNOS5440_TMU_S0_7_TRIM 0x000
89#define EXYNOS5440_TMU_S0_7_CTRL 0x020
90#define EXYNOS5440_TMU_S0_7_DEBUG 0x040
91#define EXYNOS5440_TMU_S0_7_STATUS 0x060
92#define EXYNOS5440_TMU_S0_7_TEMP 0x0f0
93#define EXYNOS5440_TMU_S0_7_TH0 0x110
94#define EXYNOS5440_TMU_S0_7_TH1 0x130
95#define EXYNOS5440_TMU_S0_7_TH2 0x150
96#define EXYNOS5440_TMU_S0_7_IRQEN 0x210
97#define EXYNOS5440_TMU_S0_7_IRQ 0x230
98/* exynos5440 common registers */
99#define EXYNOS5440_TMU_IRQ_STATUS 0x000
100#define EXYNOS5440_TMU_PMIN 0x004
101
102#define EXYNOS5440_TMU_INTEN_RISE0_SHIFT 0
103#define EXYNOS5440_TMU_INTEN_RISE1_SHIFT 1
104#define EXYNOS5440_TMU_INTEN_RISE2_SHIFT 2
105#define EXYNOS5440_TMU_INTEN_RISE3_SHIFT 3
106#define EXYNOS5440_TMU_INTEN_FALL0_SHIFT 4
107#define EXYNOS5440_TMU_TH_RISE4_SHIFT 24
108#define EXYNOS5440_EFUSE_SWAP_OFFSET 8
109
110#if defined(CONFIG_SOC_EXYNOS3250)
111extern struct exynos_tmu_init_data const exynos3250_default_tmu_data;
112#define EXYNOS3250_TMU_DRV_DATA (&exynos3250_default_tmu_data)
113#else
114#define EXYNOS3250_TMU_DRV_DATA (NULL)
115#endif
116
117#if defined(CONFIG_CPU_EXYNOS4210)
118extern struct exynos_tmu_init_data const exynos4210_default_tmu_data;
119#define EXYNOS4210_TMU_DRV_DATA (&exynos4210_default_tmu_data)
120#else
121#define EXYNOS4210_TMU_DRV_DATA (NULL)
122#endif
123
124#if defined(CONFIG_SOC_EXYNOS4412)
125extern struct exynos_tmu_init_data const exynos4412_default_tmu_data;
126#define EXYNOS4412_TMU_DRV_DATA (&exynos4412_default_tmu_data)
127#else
128#define EXYNOS4412_TMU_DRV_DATA (NULL)
129#endif
130
131#if defined(CONFIG_SOC_EXYNOS5250)
132extern struct exynos_tmu_init_data const exynos5250_default_tmu_data;
133#define EXYNOS5250_TMU_DRV_DATA (&exynos5250_default_tmu_data)
134#else
135#define EXYNOS5250_TMU_DRV_DATA (NULL)
136#endif
137
138#if defined(CONFIG_SOC_EXYNOS5260)
139extern struct exynos_tmu_init_data const exynos5260_default_tmu_data;
140#define EXYNOS5260_TMU_DRV_DATA (&exynos5260_default_tmu_data)
141#else
142#define EXYNOS5260_TMU_DRV_DATA (NULL)
143#endif
144
145#if defined(CONFIG_SOC_EXYNOS5420)
146extern struct exynos_tmu_init_data const exynos5420_default_tmu_data;
147#define EXYNOS5420_TMU_DRV_DATA (&exynos5420_default_tmu_data)
148#else
149#define EXYNOS5420_TMU_DRV_DATA (NULL)
150#endif
151
152#if defined(CONFIG_SOC_EXYNOS5440)
153extern struct exynos_tmu_init_data const exynos5440_default_tmu_data;
154#define EXYNOS5440_TMU_DRV_DATA (&exynos5440_default_tmu_data)
155#else
156#define EXYNOS5440_TMU_DRV_DATA (NULL)
157#endif
158
159#endif /*_EXYNOS_TMU_DATA_H*/
diff --git a/drivers/thermal/tegra_soctherm.c b/drivers/thermal/tegra_soctherm.c
new file mode 100644
index 000000000000..9197fc05c5cc
--- /dev/null
+++ b/drivers/thermal/tegra_soctherm.c
@@ -0,0 +1,476 @@
1/*
2 * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Author:
5 * Mikko Perttunen <mperttunen@nvidia.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/bitops.h>
19#include <linux/clk.h>
20#include <linux/delay.h>
21#include <linux/err.h>
22#include <linux/interrupt.h>
23#include <linux/io.h>
24#include <linux/module.h>
25#include <linux/of.h>
26#include <linux/platform_device.h>
27#include <linux/reset.h>
28#include <linux/thermal.h>
29
30#include <soc/tegra/fuse.h>
31
32#define SENSOR_CONFIG0 0
33#define SENSOR_CONFIG0_STOP BIT(0)
34#define SENSOR_CONFIG0_TALL_SHIFT 8
35#define SENSOR_CONFIG0_TCALC_OVER BIT(4)
36#define SENSOR_CONFIG0_OVER BIT(3)
37#define SENSOR_CONFIG0_CPTR_OVER BIT(2)
38
39#define SENSOR_CONFIG1 4
40#define SENSOR_CONFIG1_TSAMPLE_SHIFT 0
41#define SENSOR_CONFIG1_TIDDQ_EN_SHIFT 15
42#define SENSOR_CONFIG1_TEN_COUNT_SHIFT 24
43#define SENSOR_CONFIG1_TEMP_ENABLE BIT(31)
44
45#define SENSOR_CONFIG2 8
46#define SENSOR_CONFIG2_THERMA_SHIFT 16
47#define SENSOR_CONFIG2_THERMB_SHIFT 0
48
49#define SENSOR_PDIV 0x1c0
50#define SENSOR_PDIV_T124 0x8888
51#define SENSOR_HOTSPOT_OFF 0x1c4
52#define SENSOR_HOTSPOT_OFF_T124 0x00060600
53#define SENSOR_TEMP1 0x1c8
54#define SENSOR_TEMP2 0x1cc
55
56#define SENSOR_TEMP_MASK 0xffff
57#define READBACK_VALUE_MASK 0xff00
58#define READBACK_VALUE_SHIFT 8
59#define READBACK_ADD_HALF BIT(7)
60#define READBACK_NEGATE BIT(1)
61
62#define FUSE_TSENSOR8_CALIB 0x180
63#define FUSE_SPARE_REALIGNMENT_REG_0 0x1fc
64
65#define FUSE_TSENSOR_CALIB_CP_TS_BASE_MASK 0x1fff
66#define FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK (0x1fff << 13)
67#define FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT 13
68
69#define FUSE_TSENSOR8_CALIB_CP_TS_BASE_MASK 0x3ff
70#define FUSE_TSENSOR8_CALIB_FT_TS_BASE_MASK (0x7ff << 10)
71#define FUSE_TSENSOR8_CALIB_FT_TS_BASE_SHIFT 10
72
73#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_CP_MASK 0x3f
74#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_MASK (0x1f << 21)
75#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_SHIFT 21
76
77#define NOMINAL_CALIB_FT_T124 105
78#define NOMINAL_CALIB_CP_T124 25
79
80struct tegra_tsensor_configuration {
81 u32 tall, tsample, tiddq_en, ten_count, pdiv, tsample_ate, pdiv_ate;
82};
83
84struct tegra_tsensor {
85 const struct tegra_tsensor_configuration *config;
86 u32 base, calib_fuse_offset;
87 /* Correction values used to modify values read from calibration fuses */
88 s32 fuse_corr_alpha, fuse_corr_beta;
89};
90
91struct tegra_thermctl_zone {
92 void __iomem *reg;
93 unsigned int shift;
94};
95
96static const struct tegra_tsensor_configuration t124_tsensor_config = {
97 .tall = 16300,
98 .tsample = 120,
99 .tiddq_en = 1,
100 .ten_count = 1,
101 .pdiv = 8,
102 .tsample_ate = 480,
103 .pdiv_ate = 8
104};
105
106static const struct tegra_tsensor t124_tsensors[] = {
107 {
108 .config = &t124_tsensor_config,
109 .base = 0xc0,
110 .calib_fuse_offset = 0x098,
111 .fuse_corr_alpha = 1135400,
112 .fuse_corr_beta = -6266900,
113 },
114 {
115 .config = &t124_tsensor_config,
116 .base = 0xe0,
117 .calib_fuse_offset = 0x084,
118 .fuse_corr_alpha = 1122220,
119 .fuse_corr_beta = -5700700,
120 },
121 {
122 .config = &t124_tsensor_config,
123 .base = 0x100,
124 .calib_fuse_offset = 0x088,
125 .fuse_corr_alpha = 1127000,
126 .fuse_corr_beta = -6768200,
127 },
128 {
129 .config = &t124_tsensor_config,
130 .base = 0x120,
131 .calib_fuse_offset = 0x12c,
132 .fuse_corr_alpha = 1110900,
133 .fuse_corr_beta = -6232000,
134 },
135 {
136 .config = &t124_tsensor_config,
137 .base = 0x140,
138 .calib_fuse_offset = 0x158,
139 .fuse_corr_alpha = 1122300,
140 .fuse_corr_beta = -5936400,
141 },
142 {
143 .config = &t124_tsensor_config,
144 .base = 0x160,
145 .calib_fuse_offset = 0x15c,
146 .fuse_corr_alpha = 1145700,
147 .fuse_corr_beta = -7124600,
148 },
149 {
150 .config = &t124_tsensor_config,
151 .base = 0x180,
152 .calib_fuse_offset = 0x154,
153 .fuse_corr_alpha = 1120100,
154 .fuse_corr_beta = -6000500,
155 },
156 {
157 .config = &t124_tsensor_config,
158 .base = 0x1a0,
159 .calib_fuse_offset = 0x160,
160 .fuse_corr_alpha = 1106500,
161 .fuse_corr_beta = -6729300,
162 },
163};
164
165struct tegra_soctherm {
166 struct reset_control *reset;
167 struct clk *clock_tsensor;
168 struct clk *clock_soctherm;
169 void __iomem *regs;
170
171 struct thermal_zone_device *thermctl_tzs[4];
172};
173
174struct tsensor_shared_calibration {
175 u32 base_cp, base_ft;
176 u32 actual_temp_cp, actual_temp_ft;
177};
178
179static int calculate_shared_calibration(struct tsensor_shared_calibration *r)
180{
181 u32 val, shifted_cp, shifted_ft;
182 int err;
183
184 err = tegra_fuse_readl(FUSE_TSENSOR8_CALIB, &val);
185 if (err)
186 return err;
187 r->base_cp = val & FUSE_TSENSOR8_CALIB_CP_TS_BASE_MASK;
188 r->base_ft = (val & FUSE_TSENSOR8_CALIB_FT_TS_BASE_MASK)
189 >> FUSE_TSENSOR8_CALIB_FT_TS_BASE_SHIFT;
190 val = ((val & FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_MASK)
191 >> FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_SHIFT);
192 shifted_ft = sign_extend32(val, 4);
193
194 err = tegra_fuse_readl(FUSE_SPARE_REALIGNMENT_REG_0, &val);
195 if (err)
196 return err;
197 shifted_cp = sign_extend32(val, 5);
198
199 r->actual_temp_cp = 2 * NOMINAL_CALIB_CP_T124 + shifted_cp;
200 r->actual_temp_ft = 2 * NOMINAL_CALIB_FT_T124 + shifted_ft;
201
202 return 0;
203}
204
205static s64 div64_s64_precise(s64 a, s64 b)
206{
207 s64 r, al;
208
209 /* Scale up for increased precision division */
210 al = a << 16;
211
212 r = div64_s64(al * 2 + 1, 2 * b);
213 return r >> 16;
214}
215
216static int
217calculate_tsensor_calibration(const struct tegra_tsensor *sensor,
218 const struct tsensor_shared_calibration *shared,
219 u32 *calib)
220{
221 u32 val;
222 s32 actual_tsensor_ft, actual_tsensor_cp, delta_sens, delta_temp,
223 mult, div;
224 s16 therma, thermb;
225 s64 tmp;
226 int err;
227
228 err = tegra_fuse_readl(sensor->calib_fuse_offset, &val);
229 if (err)
230 return err;
231
232 actual_tsensor_cp = (shared->base_cp * 64) + sign_extend32(val, 12);
233 val = (val & FUSE_TSENSOR_CALIB_FT_TS_BASE_MASK)
234 >> FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT;
235 actual_tsensor_ft = (shared->base_ft * 32) + sign_extend32(val, 12);
236
237 delta_sens = actual_tsensor_ft - actual_tsensor_cp;
238 delta_temp = shared->actual_temp_ft - shared->actual_temp_cp;
239
240 mult = sensor->config->pdiv * sensor->config->tsample_ate;
241 div = sensor->config->tsample * sensor->config->pdiv_ate;
242
243 therma = div64_s64_precise((s64) delta_temp * (1LL << 13) * mult,
244 (s64) delta_sens * div);
245
246 tmp = (s64)actual_tsensor_ft * shared->actual_temp_cp -
247 (s64)actual_tsensor_cp * shared->actual_temp_ft;
248 thermb = div64_s64_precise(tmp, (s64)delta_sens);
249
250 therma = div64_s64_precise((s64)therma * sensor->fuse_corr_alpha,
251 (s64)1000000LL);
252 thermb = div64_s64_precise((s64)thermb * sensor->fuse_corr_alpha +
253 sensor->fuse_corr_beta, (s64)1000000LL);
254
255 *calib = ((u16)therma << SENSOR_CONFIG2_THERMA_SHIFT) |
256 ((u16)thermb << SENSOR_CONFIG2_THERMB_SHIFT);
257
258 return 0;
259}
260
261static int enable_tsensor(struct tegra_soctherm *tegra,
262 const struct tegra_tsensor *sensor,
263 const struct tsensor_shared_calibration *shared)
264{
265 void __iomem *base = tegra->regs + sensor->base;
266 unsigned int val;
267 u32 calib;
268 int err;
269
270 err = calculate_tsensor_calibration(sensor, shared, &calib);
271 if (err)
272 return err;
273
274 val = sensor->config->tall << SENSOR_CONFIG0_TALL_SHIFT;
275 writel(val, base + SENSOR_CONFIG0);
276
277 val = (sensor->config->tsample - 1) << SENSOR_CONFIG1_TSAMPLE_SHIFT;
278 val |= sensor->config->tiddq_en << SENSOR_CONFIG1_TIDDQ_EN_SHIFT;
279 val |= sensor->config->ten_count << SENSOR_CONFIG1_TEN_COUNT_SHIFT;
280 val |= SENSOR_CONFIG1_TEMP_ENABLE;
281 writel(val, base + SENSOR_CONFIG1);
282
283 writel(calib, base + SENSOR_CONFIG2);
284
285 return 0;
286}
287
288/*
289 * Translate from soctherm readback format to millicelsius.
290 * The soctherm readback format in bits is as follows:
291 * TTTTTTTT H______N
292 * where T's contain the temperature in Celsius,
293 * H denotes an addition of 0.5 Celsius and N denotes negation
294 * of the final value.
295 */
296static long translate_temp(u16 val)
297{
298 long t;
299
300 t = ((val & READBACK_VALUE_MASK) >> READBACK_VALUE_SHIFT) * 1000;
301 if (val & READBACK_ADD_HALF)
302 t += 500;
303 if (val & READBACK_NEGATE)
304 t *= -1;
305
306 return t;
307}
308
309static int tegra_thermctl_get_temp(void *data, long *out_temp)
310{
311 struct tegra_thermctl_zone *zone = data;
312 u32 val;
313
314 val = (readl(zone->reg) >> zone->shift) & SENSOR_TEMP_MASK;
315 *out_temp = translate_temp(val);
316
317 return 0;
318}
319
320static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = {
321 .get_temp = tegra_thermctl_get_temp,
322};
323
324static const struct of_device_id tegra_soctherm_of_match[] = {
325 { .compatible = "nvidia,tegra124-soctherm" },
326 { },
327};
328MODULE_DEVICE_TABLE(of, tegra_soctherm_of_match);
329
330struct thermctl_zone_desc {
331 unsigned int offset;
332 unsigned int shift;
333};
334
335static const struct thermctl_zone_desc t124_thermctl_temp_zones[] = {
336 { SENSOR_TEMP1, 16 },
337 { SENSOR_TEMP2, 16 },
338 { SENSOR_TEMP1, 0 },
339 { SENSOR_TEMP2, 0 }
340};
341
342static int tegra_soctherm_probe(struct platform_device *pdev)
343{
344 struct tegra_soctherm *tegra;
345 struct thermal_zone_device *tz;
346 struct tsensor_shared_calibration shared_calib;
347 struct resource *res;
348 unsigned int i;
349 int err;
350
351 const struct tegra_tsensor *tsensors = t124_tsensors;
352
353 tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
354 if (!tegra)
355 return -ENOMEM;
356
357 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
358 tegra->regs = devm_ioremap_resource(&pdev->dev, res);
359 if (IS_ERR(tegra->regs))
360 return PTR_ERR(tegra->regs);
361
362 tegra->reset = devm_reset_control_get(&pdev->dev, "soctherm");
363 if (IS_ERR(tegra->reset)) {
364 dev_err(&pdev->dev, "can't get soctherm reset\n");
365 return PTR_ERR(tegra->reset);
366 }
367
368 tegra->clock_tsensor = devm_clk_get(&pdev->dev, "tsensor");
369 if (IS_ERR(tegra->clock_tsensor)) {
370 dev_err(&pdev->dev, "can't get tsensor clock\n");
371 return PTR_ERR(tegra->clock_tsensor);
372 }
373
374 tegra->clock_soctherm = devm_clk_get(&pdev->dev, "soctherm");
375 if (IS_ERR(tegra->clock_soctherm)) {
376 dev_err(&pdev->dev, "can't get soctherm clock\n");
377 return PTR_ERR(tegra->clock_soctherm);
378 }
379
380 reset_control_assert(tegra->reset);
381
382 err = clk_prepare_enable(tegra->clock_soctherm);
383 if (err)
384 return err;
385
386 err = clk_prepare_enable(tegra->clock_tsensor);
387 if (err) {
388 clk_disable_unprepare(tegra->clock_soctherm);
389 return err;
390 }
391
392 reset_control_deassert(tegra->reset);
393
394 /* Initialize raw sensors */
395
396 err = calculate_shared_calibration(&shared_calib);
397 if (err)
398 goto disable_clocks;
399
400 for (i = 0; i < ARRAY_SIZE(t124_tsensors); ++i) {
401 err = enable_tsensor(tegra, tsensors + i, &shared_calib);
402 if (err)
403 goto disable_clocks;
404 }
405
406 writel(SENSOR_PDIV_T124, tegra->regs + SENSOR_PDIV);
407 writel(SENSOR_HOTSPOT_OFF_T124, tegra->regs + SENSOR_HOTSPOT_OFF);
408
409 /* Initialize thermctl sensors */
410
411 for (i = 0; i < ARRAY_SIZE(tegra->thermctl_tzs); ++i) {
412 struct tegra_thermctl_zone *zone =
413 devm_kzalloc(&pdev->dev, sizeof(*zone), GFP_KERNEL);
414 if (!zone) {
415 err = -ENOMEM;
416 goto unregister_tzs;
417 }
418
419 zone->reg = tegra->regs + t124_thermctl_temp_zones[i].offset;
420 zone->shift = t124_thermctl_temp_zones[i].shift;
421
422 tz = thermal_zone_of_sensor_register(&pdev->dev, i, zone,
423 &tegra_of_thermal_ops);
424 if (IS_ERR(tz)) {
425 err = PTR_ERR(tz);
426 dev_err(&pdev->dev, "failed to register sensor: %d\n",
427 err);
428 goto unregister_tzs;
429 }
430
431 tegra->thermctl_tzs[i] = tz;
432 }
433
434 return 0;
435
436unregister_tzs:
437 while (i--)
438 thermal_zone_of_sensor_unregister(&pdev->dev,
439 tegra->thermctl_tzs[i]);
440
441disable_clocks:
442 clk_disable_unprepare(tegra->clock_tsensor);
443 clk_disable_unprepare(tegra->clock_soctherm);
444
445 return err;
446}
447
448static int tegra_soctherm_remove(struct platform_device *pdev)
449{
450 struct tegra_soctherm *tegra = platform_get_drvdata(pdev);
451 unsigned int i;
452
453 for (i = 0; i < ARRAY_SIZE(tegra->thermctl_tzs); ++i) {
454 thermal_zone_of_sensor_unregister(&pdev->dev,
455 tegra->thermctl_tzs[i]);
456 }
457
458 clk_disable_unprepare(tegra->clock_tsensor);
459 clk_disable_unprepare(tegra->clock_soctherm);
460
461 return 0;
462}
463
464static struct platform_driver tegra_soctherm_driver = {
465 .probe = tegra_soctherm_probe,
466 .remove = tegra_soctherm_remove,
467 .driver = {
468 .name = "tegra-soctherm",
469 .of_match_table = tegra_soctherm_of_match,
470 },
471};
472module_platform_driver(tegra_soctherm_driver);
473
474MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>");
475MODULE_DESCRIPTION("NVIDIA Tegra SOCTHERM thermal management driver");
476MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 43b90709585f..84fdf0792e27 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -368,7 +368,7 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
368 tz->ops->get_trip_temp(tz, trip, &trip_temp); 368 tz->ops->get_trip_temp(tz, trip, &trip_temp);
369 369
370 /* If we have not crossed the trip_temp, we do not care. */ 370 /* If we have not crossed the trip_temp, we do not care. */
371 if (tz->temperature < trip_temp) 371 if (trip_temp <= 0 || tz->temperature < trip_temp)
372 return; 372 return;
373 373
374 trace_thermal_zone_trip(tz, trip, trip_type); 374 trace_thermal_zone_trip(tz, trip, trip_type);
@@ -757,6 +757,7 @@ policy_store(struct device *dev, struct device_attribute *attr,
757 snprintf(name, sizeof(name), "%s", buf); 757 snprintf(name, sizeof(name), "%s", buf);
758 758
759 mutex_lock(&thermal_governor_lock); 759 mutex_lock(&thermal_governor_lock);
760 mutex_lock(&tz->lock);
760 761
761 gov = __find_governor(strim(name)); 762 gov = __find_governor(strim(name));
762 if (!gov) 763 if (!gov)
@@ -766,6 +767,7 @@ policy_store(struct device *dev, struct device_attribute *attr,
766 ret = count; 767 ret = count;
767 768
768exit: 769exit:
770 mutex_unlock(&tz->lock);
769 mutex_unlock(&thermal_governor_lock); 771 mutex_unlock(&thermal_governor_lock);
770 return ret; 772 return ret;
771} 773}
@@ -1835,10 +1837,10 @@ static int __init thermal_init(void)
1835 1837
1836exit_netlink: 1838exit_netlink:
1837 genetlink_exit(); 1839 genetlink_exit();
1838unregister_governors:
1839 thermal_unregister_governors();
1840unregister_class: 1840unregister_class:
1841 class_unregister(&thermal_class); 1841 class_unregister(&thermal_class);
1842unregister_governors:
1843 thermal_unregister_governors();
1842error: 1844error:
1843 idr_destroy(&thermal_tz_idr); 1845 idr_destroy(&thermal_tz_idr);
1844 idr_destroy(&thermal_cdev_idr); 1846 idr_destroy(&thermal_cdev_idr);
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index d15d243de27a..9083e7520623 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -89,9 +89,27 @@ static inline void thermal_gov_user_space_unregister(void) {}
89#ifdef CONFIG_THERMAL_OF 89#ifdef CONFIG_THERMAL_OF
90int of_parse_thermal_zones(void); 90int of_parse_thermal_zones(void);
91void of_thermal_destroy_zones(void); 91void of_thermal_destroy_zones(void);
92int of_thermal_get_ntrips(struct thermal_zone_device *);
93bool of_thermal_is_trip_valid(struct thermal_zone_device *, int);
94const struct thermal_trip * const
95of_thermal_get_trip_points(struct thermal_zone_device *);
92#else 96#else
93static inline int of_parse_thermal_zones(void) { return 0; } 97static inline int of_parse_thermal_zones(void) { return 0; }
94static inline void of_thermal_destroy_zones(void) { } 98static inline void of_thermal_destroy_zones(void) { }
99static inline int of_thermal_get_ntrips(struct thermal_zone_device *tz)
100{
101 return 0;
102}
103static inline bool of_thermal_is_trip_valid(struct thermal_zone_device *tz,
104 int trip)
105{
106 return 0;
107}
108static inline const struct thermal_trip * const
109of_thermal_get_trip_points(struct thermal_zone_device *tz)
110{
111 return NULL;
112}
95#endif 113#endif
96 114
97#endif /* __THERMAL_CORE_H__ */ 115#endif /* __THERMAL_CORE_H__ */
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
index 9eec26dc0448..5fd03865e396 100644
--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -286,6 +286,11 @@ static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
286 return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp); 286 return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp);
287} 287}
288 288
289static const struct thermal_zone_of_device_ops ti_of_thermal_ops = {
290 .get_temp = __ti_thermal_get_temp,
291 .get_trend = __ti_thermal_get_trend,
292};
293
289static struct thermal_zone_device_ops ti_thermal_ops = { 294static struct thermal_zone_device_ops ti_thermal_ops = {
290 .get_temp = ti_thermal_get_temp, 295 .get_temp = ti_thermal_get_temp,
291 .get_trend = ti_thermal_get_trend, 296 .get_trend = ti_thermal_get_trend,
@@ -333,8 +338,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
333 338
334 /* in case this is specified by DT */ 339 /* in case this is specified by DT */
335 data->ti_thermal = thermal_zone_of_sensor_register(bgp->dev, id, 340 data->ti_thermal = thermal_zone_of_sensor_register(bgp->dev, id,
336 data, __ti_thermal_get_temp, 341 data, &ti_of_thermal_ops);
337 __ti_thermal_get_trend);
338 if (IS_ERR(data->ti_thermal)) { 342 if (IS_ERR(data->ti_thermal)) {
339 /* Create thermal zone */ 343 /* Create thermal zone */
340 data->ti_thermal = thermal_zone_device_register(domain, 344 data->ti_thermal = thermal_zone_device_register(domain,
diff --git a/include/dt-bindings/thermal/tegra124-soctherm.h b/include/dt-bindings/thermal/tegra124-soctherm.h
new file mode 100644
index 000000000000..85aaf66690f9
--- /dev/null
+++ b/include/dt-bindings/thermal/tegra124-soctherm.h
@@ -0,0 +1,13 @@
1/*
2 * This header provides constants for binding nvidia,tegra124-soctherm.
3 */
4
5#ifndef _DT_BINDINGS_THERMAL_TEGRA124_SOCTHERM_H
6#define _DT_BINDINGS_THERMAL_TEGRA124_SOCTHERM_H
7
8#define TEGRA124_SOCTHERM_SENSOR_CPU 0
9#define TEGRA124_SOCTHERM_SENSOR_MEM 1
10#define TEGRA124_SOCTHERM_SENSOR_GPU 2
11#define TEGRA124_SOCTHERM_SENSOR_PLLX 3
12
13#endif
diff --git a/include/linux/clock_cooling.h b/include/linux/clock_cooling.h
new file mode 100644
index 000000000000..4d1019d56f7f
--- /dev/null
+++ b/include/linux/clock_cooling.h
@@ -0,0 +1,65 @@
1/*
2 * linux/include/linux/clock_cooling.h
3 *
4 * Copyright (C) 2014 Eduardo Valentin <edubezval@gmail.com>
5 *
6 * Copyright (C) 2013 Texas Instruments Inc.
7 * Contact: Eduardo Valentin <eduardo.valentin@ti.com>
8 *
9 * Highly based on cpu_cooling.c.
10 * Copyright (C) 2012 Samsung Electronics Co., Ltd(http://www.samsung.com)
11 * Copyright (C) 2012 Amit Daniel <amit.kachhap@linaro.org>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; version 2 of the License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 */
22
23#ifndef __CPU_COOLING_H__
24#define __CPU_COOLING_H__
25
26#include <linux/of.h>
27#include <linux/thermal.h>
28#include <linux/cpumask.h>
29
30#ifdef CONFIG_CLOCK_THERMAL
31/**
32 * clock_cooling_register - function to create clock cooling device.
33 * @dev: struct device pointer to the device used as clock cooling device.
34 * @clock_name: string containing the clock used as cooling mechanism.
35 */
36struct thermal_cooling_device *
37clock_cooling_register(struct device *dev, const char *clock_name);
38
39/**
40 * clock_cooling_unregister - function to remove clock cooling device.
41 * @cdev: thermal cooling device pointer.
42 */
43void clock_cooling_unregister(struct thermal_cooling_device *cdev);
44
45unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev,
46 unsigned long freq);
47#else /* !CONFIG_CLOCK_THERMAL */
48static inline struct thermal_cooling_device *
49clock_cooling_register(struct device *dev, const char *clock_name)
50{
51 return NULL;
52}
53static inline
54void clock_cooling_unregister(struct thermal_cooling_device *cdev)
55{
56}
57static inline
58unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev,
59 unsigned long freq)
60{
61 return THERMAL_CSTATE_INVALID;
62}
63#endif /* CONFIG_CLOCK_THERMAL */
64
65#endif /* __CPU_COOLING_H__ */
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index ef90838b36a0..c611a02fbc51 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -29,10 +29,10 @@
29#include <linux/idr.h> 29#include <linux/idr.h>
30#include <linux/device.h> 30#include <linux/device.h>
31#include <linux/workqueue.h> 31#include <linux/workqueue.h>
32#include <uapi/linux/thermal.h>
32 33
33#define THERMAL_TRIPS_NONE -1 34#define THERMAL_TRIPS_NONE -1
34#define THERMAL_MAX_TRIPS 12 35#define THERMAL_MAX_TRIPS 12
35#define THERMAL_NAME_LENGTH 20
36 36
37/* invalid cooling state */ 37/* invalid cooling state */
38#define THERMAL_CSTATE_INVALID -1UL 38#define THERMAL_CSTATE_INVALID -1UL
@@ -49,11 +49,6 @@
49#define MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, off) (((t) / 100) + (off)) 49#define MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, off) (((t) / 100) + (off))
50#define MILLICELSIUS_TO_DECI_KELVIN(t) MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, 2732) 50#define MILLICELSIUS_TO_DECI_KELVIN(t) MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, 2732)
51 51
52/* Adding event notification support elements */
53#define THERMAL_GENL_FAMILY_NAME "thermal_event"
54#define THERMAL_GENL_VERSION 0x01
55#define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_grp"
56
57/* Default Thermal Governor */ 52/* Default Thermal Governor */
58#if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE) 53#if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE)
59#define DEFAULT_THERMAL_GOVERNOR "step_wise" 54#define DEFAULT_THERMAL_GOVERNOR "step_wise"
@@ -86,30 +81,6 @@ enum thermal_trend {
86 THERMAL_TREND_DROP_FULL, /* apply lowest cooling action */ 81 THERMAL_TREND_DROP_FULL, /* apply lowest cooling action */
87}; 82};
88 83
89/* Events supported by Thermal Netlink */
90enum events {
91 THERMAL_AUX0,
92 THERMAL_AUX1,
93 THERMAL_CRITICAL,
94 THERMAL_DEV_FAULT,
95};
96
97/* attributes of thermal_genl_family */
98enum {
99 THERMAL_GENL_ATTR_UNSPEC,
100 THERMAL_GENL_ATTR_EVENT,
101 __THERMAL_GENL_ATTR_MAX,
102};
103#define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)
104
105/* commands supported by the thermal_genl_family */
106enum {
107 THERMAL_GENL_CMD_UNSPEC,
108 THERMAL_GENL_CMD_EVENT,
109 __THERMAL_GENL_CMD_MAX,
110};
111#define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
112
113struct thermal_zone_device_ops { 84struct thermal_zone_device_ops {
114 int (*bind) (struct thermal_zone_device *, 85 int (*bind) (struct thermal_zone_device *,
115 struct thermal_cooling_device *); 86 struct thermal_cooling_device *);
@@ -289,19 +260,49 @@ struct thermal_genl_event {
289 enum events event; 260 enum events event;
290}; 261};
291 262
263/**
264 * struct thermal_zone_of_device_ops - scallbacks for handling DT based zones
265 *
266 * Mandatory:
267 * @get_temp: a pointer to a function that reads the sensor temperature.
268 *
269 * Optional:
270 * @get_trend: a pointer to a function that reads the sensor temperature trend.
271 * @set_emul_temp: a pointer to a function that sets sensor emulated
272 * temperature.
273 */
274struct thermal_zone_of_device_ops {
275 int (*get_temp)(void *, long *);
276 int (*get_trend)(void *, long *);
277 int (*set_emul_temp)(void *, unsigned long);
278};
279
280/**
281 * struct thermal_trip - representation of a point in temperature domain
282 * @np: pointer to struct device_node that this trip point was created from
283 * @temperature: temperature value in miliCelsius
284 * @hysteresis: relative hysteresis in miliCelsius
285 * @type: trip point type
286 */
287
288struct thermal_trip {
289 struct device_node *np;
290 unsigned long int temperature;
291 unsigned long int hysteresis;
292 enum thermal_trip_type type;
293};
294
292/* Function declarations */ 295/* Function declarations */
293#ifdef CONFIG_THERMAL_OF 296#ifdef CONFIG_THERMAL_OF
294struct thermal_zone_device * 297struct thermal_zone_device *
295thermal_zone_of_sensor_register(struct device *dev, int id, 298thermal_zone_of_sensor_register(struct device *dev, int id, void *data,
296 void *data, int (*get_temp)(void *, long *), 299 const struct thermal_zone_of_device_ops *ops);
297 int (*get_trend)(void *, long *));
298void thermal_zone_of_sensor_unregister(struct device *dev, 300void thermal_zone_of_sensor_unregister(struct device *dev,
299 struct thermal_zone_device *tz); 301 struct thermal_zone_device *tz);
300#else 302#else
301static inline struct thermal_zone_device * 303static inline struct thermal_zone_device *
302thermal_zone_of_sensor_register(struct device *dev, int id, 304thermal_zone_of_sensor_register(struct device *dev, int id, void *data,
303 void *data, int (*get_temp)(void *, long *), 305 const struct thermal_zone_of_device_ops *ops)
304 int (*get_trend)(void *, long *))
305{ 306{
306 return NULL; 307 return NULL;
307} 308}
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index 259d31fc9073..00b100023c47 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -387,6 +387,7 @@ header-y += tcp.h
387header-y += tcp_metrics.h 387header-y += tcp_metrics.h
388header-y += telephony.h 388header-y += telephony.h
389header-y += termios.h 389header-y += termios.h
390header-y += thermal.h
390header-y += time.h 391header-y += time.h
391header-y += times.h 392header-y += times.h
392header-y += timex.h 393header-y += timex.h
diff --git a/include/uapi/linux/thermal.h b/include/uapi/linux/thermal.h
new file mode 100644
index 000000000000..ac5535855982
--- /dev/null
+++ b/include/uapi/linux/thermal.h
@@ -0,0 +1,35 @@
1#ifndef _UAPI_LINUX_THERMAL_H
2#define _UAPI_LINUX_THERMAL_H
3
4#define THERMAL_NAME_LENGTH 20
5
6/* Adding event notification support elements */
7#define THERMAL_GENL_FAMILY_NAME "thermal_event"
8#define THERMAL_GENL_VERSION 0x01
9#define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_grp"
10
11/* Events supported by Thermal Netlink */
12enum events {
13 THERMAL_AUX0,
14 THERMAL_AUX1,
15 THERMAL_CRITICAL,
16 THERMAL_DEV_FAULT,
17};
18
19/* attributes of thermal_genl_family */
20enum {
21 THERMAL_GENL_ATTR_UNSPEC,
22 THERMAL_GENL_ATTR_EVENT,
23 __THERMAL_GENL_ATTR_MAX,
24};
25#define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)
26
27/* commands supported by the thermal_genl_family */
28enum {
29 THERMAL_GENL_CMD_UNSPEC,
30 THERMAL_GENL_CMD_EVENT,
31 __THERMAL_GENL_CMD_MAX,
32};
33#define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
34
35#endif /* _UAPI_LINUX_THERMAL_H */