History

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 ...

Linus Torvalds committed 11 years ago

Commit 2efda902 parents 0b4954c 2707dbd34 files · +2787 −858Browse files

Unified · Split

34 files
  1. Documentation/devicetree/bindings/thermal/armada-thermal.txt +0 −8
  2. Documentation/devicetree/bindings/thermal/rockchip-thermal.txt +68 −0
  3. Documentation/devicetree/bindings/thermal/tegra-soctherm.txt +53 −0
  4. MAINTAINERS +1 −0
  5. arch/arm/boot/dts/tegra124-jetson-tk1.dts +44 −0
  6. arch/arm/boot/dts/tegra124.dtsi +47 −0
  7. drivers/hwmon/lm75.c +6 −3
  8. drivers/hwmon/ntc_thermistor.c +5 −1
  9. drivers/hwmon/tmp102.c +5 −1
  10. drivers/thermal/Kconfig +32 −0
  11. drivers/thermal/Makefile +5 −0
  12. drivers/thermal/armada_thermal.c +0 −20
  13. drivers/thermal/clock_cooling.c +485 −0
  14. drivers/thermal/int340x_thermal/acpi_thermal_rel.c +7 −5
  15. drivers/thermal/int340x_thermal/int3400_thermal.c +78 −2
  16. drivers/thermal/int340x_thermal/int3403_thermal.c +1 −3
  17. drivers/thermal/intel_powerclamp.c +1 −0
  18. drivers/thermal/intel_soc_dts_thermal.c +7 −5
  19. drivers/thermal/of-thermal.c +108 −40
  20. drivers/thermal/rockchip_thermal.c +693 −0
  21. drivers/thermal/samsung/exynos_thermal_common.h +0 −1
  22. drivers/thermal/samsung/exynos_tmu.c +468 −224
  23. drivers/thermal/samsung/exynos_tmu.h +9 −114
  24. drivers/thermal/samsung/exynos_tmu_data.c +8 −231
  25. drivers/thermal/samsung/exynos_tmu_data.h +0 −159
  26. drivers/thermal/tegra_soctherm.c +476 −0
  27. drivers/thermal/thermal_core.c +5 −3
  28. drivers/thermal/thermal_core.h +18 −0
  29. drivers/thermal/ti-soc-thermal/ti-thermal-common.c +6 −2
  30. include/dt-bindings/thermal/tegra124-soctherm.h +13 −0
  31. include/linux/clock_cooling.h +65 −0
  32. include/linux/thermal.h +37 −36
  33. include/uapi/linux/Kbuild +1 −0
  34. include/uapi/linux/thermal.h +35 −0
Documentation/devicetree/bindings/thermal/armada-thermal.txt+0−8
@@ -5,17 +5,9 @@ Required properties: · 4 unmodified lines
55 - compatible: Should be set to one of the following:
66 marvell,armada370-thermal
77 marvell,armada375-thermal
8− marvell,armada375-z1-thermal
98 marvell,armada380-thermal
109 marvell,armadaxp-thermal
1110
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−
1911 - reg: Device's register space.
2012 Two entries are expected, see the examples below.
2113 The first one is required for the sensor register;
Documentation/devicetree/bindings/thermal/rockchip-thermal.txt+68−0
@@ -0,0 +1,68 @@
1+* Temperature Sensor ADC (TSADC) on rockchip SoCs
2+
3+Required 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+
21+Exiample:
22+tsadc: 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+
38+Example: referring to thermal sensors:
39+thermal-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+};
Documentation/devicetree/bindings/thermal/tegra-soctherm.txt+53−0
@@ -0,0 +1,53 @@
1+Tegra124 SOCTHERM thermal management system
2+
3+The SOCTHERM IP block contains thermal sensors, support for polled
4+or interrupt-based thermal monitoring, CPU and GPU throttling based
5+on temperature trip points, and handling external overcurrent
6+notifications. It is also used to manage emergency shutdown in an
7+overheating situation.
8+
9+Required 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+
28+Example :
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+
43+Example: 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+ };
MAINTAINERS+1−0
@@ -9516,6 +9516,7 @@ Q: https://patchwork.kernel.org/project/linux-pm/list/ · 9515 unmodified lines
95169516 S: Supported
95179517 F: drivers/thermal/
95189518 F: include/linux/thermal.h
9519+F: include/uapi/linux/thermal.h
95199520 F: include/linux/cpu_cooling.h
95209521 F: Documentation/devicetree/bindings/thermal/
95219522
arch/arm/boot/dts/tegra124-jetson-tk1.dts+44−0
@@ -1942,4 +1942,48 @@ · 1941 unmodified lines
19421942 <&tegra_car TEGRA124_CLK_EXTERN1>;
19431943 clock-names = "pll_a", "pll_a_out0", "mclk";
19441944 };
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+ };
19451989 };
arch/arm/boot/dts/tegra124.dtsi+47−0
@@ -4,6 +4,7 @@ · 3 unmodified lines
44 #include <dt-bindings/pinctrl/pinctrl-tegra.h>
55 #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
66 #include <dt-bindings/interrupt-controller/arm-gic.h>
7+#include <dt-bindings/thermal/tegra124-soctherm.h>
78
89 #include "skeleton.dtsi"
910
@@ -657,6 +658,18 @@ · 647 unmodified lines
657658 status = "disabled";
658659 };
659660
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+
660673 ahub@0,70300000 {
661674 compatible = "nvidia,tegra124-ahub";
662675 reg = <0x0 0x70300000 0x0 0x200>,
@@ -898,6 +911,40 @@ · 235 unmodified lines
898911 };
899912 };
900913
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+
901948 timer {
902949 compatible = "arm,armv7-timer";
903950 interrupts = <GIC_PPI 13
drivers/hwmon/lm75.c+6−3
@@ -177,6 +177,10 @@ static struct attribute *lm75_attrs[] = { · 176 unmodified lines
177177 };
178178 ATTRIBUTE_GROUPS(lm75);
179179
180+static const struct thermal_zone_of_device_ops lm75_of_thermal_ops = {
181+ .get_temp = lm75_read_temp,
182+};
183+
180184 /*-----------------------------------------------------------------------*/
181185
182186 /* device probe and removal */
@@ -296,10 +300,9 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) · 113 unmodified lines
296300 if (IS_ERR(data->hwmon_dev))
297301 return PTR_ERR(data->hwmon_dev);
298302
299− data->tz = thermal_zone_of_sensor_register(data->hwmon_dev,
300− 0,
303+ data->tz = thermal_zone_of_sensor_register(data->hwmon_dev, 0,
301304 data->hwmon_dev,
302− lm75_read_temp, NULL);
305+ &lm75_of_thermal_ops);
303306 if (IS_ERR(data->tz))
304307 data->tz = NULL;
305308
drivers/hwmon/ntc_thermistor.c+5−1
@@ -486,6 +486,10 @@ static const struct attribute_group ntc_attr_group = { · 485 unmodified lines
486486 .attrs = ntc_attributes,
487487 };
488488
489+static const struct thermal_zone_of_device_ops ntc_of_thermal_ops = {
490+ .get_temp = ntc_read_temp,
491+};
492+
489493 static int ntc_thermistor_probe(struct platform_device *pdev)
490494 {
491495 const struct of_device_id *of_id =
@@ -579,7 +583,7 @@ static int ntc_thermistor_probe(struct platform_device *pdev) · 87 unmodified lines
579583 pdev_id->name);
580584
581585 data->tz = thermal_zone_of_sensor_register(data->dev, 0, data->dev,
582− ntc_read_temp, NULL);
586+ &ntc_of_thermal_ops);
583587 if (IS_ERR(data->tz)) {
584588 dev_dbg(&pdev->dev, "Failed to register to thermal fw.\n");
585589 data->tz = NULL;
drivers/hwmon/tmp102.c+5−1
@@ -158,6 +158,10 @@ ATTRIBUTE_GROUPS(tmp102); · 157 unmodified lines
158158 #define TMP102_CONFIG (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1)
159159 #define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL)
160160
161+static const struct thermal_zone_of_device_ops tmp102_of_thermal_ops = {
162+ .get_temp = tmp102_read_temp,
163+};
164+
161165 static int tmp102_probe(struct i2c_client *client,
162166 const struct i2c_device_id *id)
163167 {
@@ -215,7 +219,7 @@ static int tmp102_probe(struct i2c_client *client, · 51 unmodified lines
215219 }
216220 tmp102->hwmon_dev = hwmon_dev;
217221 tmp102->tz = thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev,
218− tmp102_read_temp, NULL);
222+ &tmp102_of_thermal_ops);
219223 if (IS_ERR(tmp102->tz))
220224 tmp102->tz = NULL;
221225
drivers/thermal/Kconfig+32−0
@@ -112,6 +112,18 @@ config CPU_THERMAL · 111 unmodified lines
112112
113113 If you want this support, you should say Y here.
114114
115+config 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+
115127 config THERMAL_EMULATION
116128 bool "Thermal emulation mode support"
117129 help
@@ -143,6 +155,16 @@ config SPEAR_THERMAL · 25 unmodified lines
143155 Enable this to plug the SPEAr thermal sensor driver into the Linux
144156 thermal framework.
145157
158+config 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+
146168 config RCAR_THERMAL
147169 tristate "Renesas R-Car thermal driver"
148170 depends on ARCH_SHMOBILE || COMPILE_TEST
@@ -185,6 +207,16 @@ config ARMADA_THERMAL · 36 unmodified lines
185207 Enable this option if you want to have support for thermal management
186208 controller present in Armada 370 and Armada XP SoC.
187209
210+config 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+
188220 config DB8500_CPUFREQ_COOLING
189221 tristate "DB8500 cpufreq cooling"
190222 depends on ARCH_U8500
drivers/thermal/Makefile+5−0
@@ -18,8 +18,12 @@ thermal_sys-$(CONFIG_THERMAL_GOV_USER_SPACE) += user_space.o · 17 unmodified lines
1818 # cpufreq cooling
1919 thermal_sys-$(CONFIG_CPU_THERMAL) += cpu_cooling.o
2020
21+# clock cooling
22+thermal_sys-$(CONFIG_CLOCK_THERMAL) += clock_cooling.o
23+
2124 # platform thermal drivers
2225 obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
26+obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
2327 obj-$(CONFIG_RCAR_THERMAL) += rcar_thermal.o
2428 obj-$(CONFIG_KIRKWOOD_THERMAL) += kirkwood_thermal.o
2529 obj-y += samsung/
@@ -34,3 +38,4 @@ obj-$(CONFIG_INTEL_SOC_DTS_THERMAL) += intel_soc_dts_thermal.o · 8 unmodified lines
3438 obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/
3539 obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/
3640 obj-$(CONFIG_ST_THERMAL) += st/
41+obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o
drivers/thermal/armada_thermal.c+0−20
@@ -35,10 +35,6 @@ · 34 unmodified lines
3535 #define PMU_TDC0_OTF_CAL_MASK (0x1 << 30)
3636 #define PMU_TDC0_START_CAL_MASK (0x1 << 25)
3737
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−
4238 #define A375_UNIT_CONTROL_SHIFT 27
4339 #define A375_UNIT_CONTROL_MASK 0x7
4440 #define A375_READOUT_INVERT BIT(15)
@@ -124,24 +120,12 @@ static void armada375_init_sensor(struct platform_device *pdev, · 79 unmodified lines
124120 struct armada_thermal_priv *priv)
125121 {
126122 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− }
136123
137124 reg = readl(priv->control + 4);
138125 reg &= ~(A375_UNIT_CONTROL_MASK << A375_UNIT_CONTROL_SHIFT);
139126 reg &= ~A375_READOUT_INVERT;
140127 reg &= ~A375_HW_RESETn;
141128
142− if (quirk_needed)
143− reg |= A375_Z1_WORKAROUND_BIT;
144−
145129 writel(reg, priv->control + 4);
146130 mdelay(20);
147131
@@ -259,10 +243,6 @@ static const struct of_device_id armada_thermal_id_table[] = { · 111 unmodified lines
259243 .compatible = "marvell,armada375-thermal",
260244 .data = &armada375_data,
261245 },
262− {
263− .compatible = "marvell,armada375-z1-thermal",
264− .data = &armada375_data,
265− },
266246 {
267247 .compatible = "marvell,armada380-thermal",
268248 .data = &armada380_data,
drivers/thermal/clock_cooling.c+485−0
@@ -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+ */
55+struct 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)
68+static DEFINE_IDR(clock_idr);
69+static 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+ */
80+static 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+ */
98+static 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+
107+enum 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+ */
132+static 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+ */
214+unsigned 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+}
226+EXPORT_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+ */
240+static unsigned long
241+clock_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+ */
266+static 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+ */
306+static 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+ */
342+static 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+ */
366+static 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+ */
386+static 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 */
395+static 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+ */
417+struct thermal_cooling_device *
418+clock_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+}
462+EXPORT_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+ */
470+void 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+}
485+EXPORT_SYMBOL_GPL(clock_cooling_unregister);
drivers/thermal/int340x_thermal/acpi_thermal_rel.c+7−5
@@ -131,6 +131,8 @@ int acpi_parse_trt(acpi_handle handle, int *trt_count, struct trt **trtp, · 130 unmodified lines
131131 pr_warn("Failed to get target ACPI device\n");
132132 }
133133
134+ result = 0;
135+
134136 *trtp = trts;
135137 /* don't count bad entries */
136138 *trt_count -= nr_bad_entries;
@@ -317,21 +319,21 @@ static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd, · 180 unmodified lines
317319 {
318320 int ret = 0;
319321 unsigned long length = 0;
320− unsigned long count = 0;
322+ int count = 0;
321323 char __user *arg = (void __user *)__arg;
322324 struct trt *trts;
323325 struct art *arts;
324326
325327 switch (cmd) {
326328 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,
328330 &trts, false);
329331 kfree(trts);
330332 if (!ret)
331333 return put_user(count, (unsigned long __user *)__arg);
332334 return ret;
333335 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,
335337 &trts, false);
336338 kfree(trts);
337339 length = count * sizeof(union trt_object);
@@ -341,14 +343,14 @@ static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd, · 3 unmodified lines
341343 case ACPI_THERMAL_GET_TRT:
342344 return fill_trt(arg);
343345 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,
345347 &arts, false);
346348 kfree(arts);
347349 if (!ret)
348350 return put_user(count, (unsigned long __user *)__arg);
349351 return ret;
350352 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,
352354 &arts, false);
353355 kfree(arts);
354356 length = count * sizeof(union art_object);
drivers/thermal/int340x_thermal/int3400_thermal.c+78−2
@@ -43,6 +43,74 @@ struct int3400_thermal_priv { · 42 unmodified lines
4343 struct trt *trts;
4444 u8 uuid_bitmap;
4545 int rel_misc_dev_res;
46+ int current_uuid_index;
47+};
48+
49+static 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+
70+static 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+
83+static 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+
103+static DEVICE_ATTR(current_uuid, 0644, current_uuid_show, current_uuid_store);
104+static DEVICE_ATTR_RO(available_uuids);
105+static struct attribute *uuid_attrs[] = {
106+ &dev_attr_available_uuids.attr,
107+ &dev_attr_current_uuid.attr,
108+ NULL
109+};
110+
111+static struct attribute_group uuid_attribute_group = {
112+ .attrs = uuid_attrs,
113+ .name = "uuids"
46114 };
47115
48116 static 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, · 111 unmodified lines
160228
161229 if (enable != priv->mode) {
162230 priv->mode = enable;
163− /* currently, only PASSIVE COOLING is supported */
164231 result = int3400_thermal_run_osc(priv->adev->handle,
165− INT3400_THERMAL_PASSIVE_1, enable);
232+ priv->current_uuid_index,
233+ enable);
166234 }
167235 return result;
168236 }
@@ -223,7 +291,14 @@ static int int3400_thermal_probe(struct platform_device *pdev) · 54 unmodified lines
223291 priv->rel_misc_dev_res = acpi_thermal_rel_misc_device_add(
224292 priv->adev->handle);
225293
294+ result = sysfs_create_group(&pdev->dev.kobj, &uuid_attribute_group);
295+ if (result)
296+ goto free_zone;
297+
226298 return 0;
299+
300+free_zone:
301+ thermal_zone_device_unregister(priv->thermal);
227302 free_trt:
228303 kfree(priv->trts);
229304 free_art:
@@ -240,6 +315,7 @@ static int int3400_thermal_remove(struct platform_device *pdev) · 10 unmodified lines
240315 if (!priv->rel_misc_dev_res)
241316 acpi_thermal_rel_misc_device_remove(priv->adev->handle);
242317
318+ sysfs_remove_group(&pdev->dev.kobj, &uuid_attribute_group);
243319 thermal_zone_device_unregister(priv->thermal);
244320 kfree(priv->trts);
245321 kfree(priv->arts);
drivers/thermal/int340x_thermal/int3403_thermal.c+1−3
@@ -293,8 +293,7 @@ static int int3403_sensor_add(struct int3403_priv *priv) · 292 unmodified lines
293293 return 0;
294294
295295 err_free_obj:
296− if (obj->tzone)
297− thermal_zone_device_unregister(obj->tzone);
296+ thermal_zone_device_unregister(obj->tzone);
298297 return result;
299298 }
300299
@@ -471,7 +470,6 @@ static struct platform_driver int3403_driver = { · 170 unmodified lines
471470 .remove = int3403_remove,
472471 .driver = {
473472 .name = "int3403 thermal",
474− .owner = THIS_MODULE,
475473 .acpi_match_table = int3403_device_ids,
476474 },
477475 };
drivers/thermal/intel_powerclamp.c+1−0
@@ -689,6 +689,7 @@ static const struct x86_cpu_id intel_powerclamp_ids[] = { · 688 unmodified lines
689689 { X86_VENDOR_INTEL, 6, 0x3f},
690690 { X86_VENDOR_INTEL, 6, 0x45},
691691 { X86_VENDOR_INTEL, 6, 0x46},
692+ { X86_VENDOR_INTEL, 6, 0x4c},
692693 {}
693694 };
694695 MODULE_DEVICE_TABLE(x86cpu, intel_powerclamp_ids);
drivers/thermal/intel_soc_dts_thermal.c+7−5
@@ -360,6 +360,9 @@ static void proc_thermal_interrupt(void) · 359 unmodified lines
360360 u32 sticky_out;
361361 int status;
362362 u32 ptmc_out;
363+ unsigned long flags;
364+
365+ spin_lock_irqsave(&intr_notify_lock, flags);
363366
364367 /* Clear APIC interrupt */
365368 status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
@@ -378,21 +381,20 @@ static void proc_thermal_interrupt(void) · 12 unmodified lines
378381 /* reset sticky bit */
379382 status = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
380383 SOC_DTS_OFFSET_PTTSS, sticky_out);
384+ spin_unlock_irqrestore(&intr_notify_lock, flags);
385+
381386 for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) {
382387 pr_debug("TZD update for zone %d\n", i);
383388 thermal_zone_device_update(soc_dts[i]->tzone);
384389 }
385− }
390+ } else
391+ spin_unlock_irqrestore(&intr_notify_lock, flags);
386392
387393 }
388394
389395 static irqreturn_t soc_irq_thread_fn(int irq, void *dev_data)
390396 {
391− unsigned long flags;
392−
393− spin_lock_irqsave(&intr_notify_lock, flags);
394397 proc_thermal_interrupt();
395− spin_unlock_irqrestore(&intr_notify_lock, flags);
396398 pr_debug("proc_thermal_interrupt\n");
397399
398400 return IRQ_HANDLED;
drivers/thermal/of-thermal.c+108−40
@@ -30,26 +30,12 @@ · 29 unmodified lines
3030 #include <linux/err.h>
3131 #include <linux/export.h>
3232 #include <linux/string.h>
33+#include <linux/thermal.h>
3334
3435 #include "thermal_core.h"
3536
3637 /*** Private data structures to represent thermal device tree data ***/
3738
38−/**
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−
46−struct __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−
5339 /**
5440 * struct __thermal_bind_param - a match between trip and cooling device
5541 * @cooling_device: a pointer to identify the referred cooling device
@@ -77,8 +63,7 @@ struct __thermal_bind_params { · 21 unmodified lines
7763 * @num_tbps: number of thermal bind params
7864 * @tbps: an array of thermal bind params (0..num_tbps - 1)
7965 * @sensor_data: sensor private data used while reading temperature and trend
80− * @get_temp: sensor callback to read temperature
81− * @get_trend: sensor callback to read temperature trend
66+ * @ops: set of callbacks to handle the thermal zone based on DT
8267 */
8368
8469 struct __thermal_zone {
@@ -88,7 +73,7 @@ struct __thermal_zone { · 3 unmodified lines
8873
8974 /* trip data */
9075 int ntrips;
91− struct __thermal_trip *trips;
76+ struct thermal_trip *trips;
9277
9378 /* cooling binding data */
9479 int num_tbps;
@@ -96,8 +81,7 @@ struct __thermal_zone { · 1 unmodified line
9681
9782 /* sensor interface */
9883 void *sensor_data;
99− int (*get_temp)(void *, long *);
100− int (*get_trend)(void *, long *);
84+ const struct thermal_zone_of_device_ops *ops;
10185 };
10286
10387 /*** DT thermal zone device callbacks ***/
@@ -107,10 +91,96 @@ static int of_thermal_get_temp(struct thermal_zone_device *tz, · 3 unmodified lines
10791 {
10892 struct __thermal_zone *data = tz->devdata;
10993
110− if (!data->get_temp)
94+ if (!data->ops->get_temp)
11195 return -EINVAL;
11296
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+ */
110+int 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+}
119+EXPORT_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+ */
131+bool 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+}
140+EXPORT_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+ */
152+const struct thermal_trip * const
153+of_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+}
162+EXPORT_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+ */
175+static 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);
114184 }
115185
116186 static 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, · 3 unmodified lines
120190 long dev_trend;
121191 int r;
122192
123− if (!data->get_trend)
193+ if (!data->ops->get_trend)
124194 return -EINVAL;
125195
126− r = data->get_trend(data->sensor_data, &dev_trend);
196+ r = data->ops->get_trend(data->sensor_data, &dev_trend);
127197 if (r)
128198 return r;
129199
@@ -324,8 +394,7 @@ static struct thermal_zone_device_ops of_thermal_ops = { · 194 unmodified lines
324394 static struct thermal_zone_device *
325395 thermal_zone_of_add_sensor(struct device_node *zone,
326396 struct device_node *sensor, void *data,
327− int (*get_temp)(void *, long *),
328− int (*get_trend)(void *, long *))
397+ const struct thermal_zone_of_device_ops *ops)
329398 {
330399 struct thermal_zone_device *tzd;
331400 struct __thermal_zone *tz;
@@ -336,13 +405,16 @@ thermal_zone_of_add_sensor(struct device_node *zone, · 4 unmodified lines
336405
337406 tz = tzd->devdata;
338407
408+ if (!ops)
409+ return ERR_PTR(-EINVAL);
410+
339411 mutex_lock(&tzd->lock);
340− tz->get_temp = get_temp;
341− tz->get_trend = get_trend;
412+ tz->ops = ops;
342413 tz->sensor_data = data;
343414
344415 tzd->ops->get_temp = of_thermal_get_temp;
345416 tzd->ops->get_trend = of_thermal_get_trend;
417+ tzd->ops->set_emul_temp = of_thermal_set_emul_temp;
346418 mutex_unlock(&tzd->lock);
347419
348420 return tzd;
@@ -356,8 +428,7 @@ thermal_zone_of_add_sensor(struct device_node *zone, · 7 unmodified lines
356428 * than one sensors
357429 * @data: a private pointer (owned by the caller) that will be passed
358430 * back, when a temperature reading is needed.
359− * @get_temp: a pointer to a function that reads the sensor temperature.
360− * @get_trend: a pointer to a function that reads the sensor temperature trend.
431+ * @ops: struct thermal_zone_of_device_ops *. Must contain at least .get_temp.
361432 *
362433 * This function will search the list of thermal zones described in device
363434 * 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, · 18 unmodified lines
382453 * check the return value with help of IS_ERR() helper.
383454 */
384455 struct thermal_zone_device *
385−thermal_zone_of_sensor_register(struct device *dev, int sensor_id,
386− void *data, int (*get_temp)(void *, long *),
387− int (*get_trend)(void *, long *))
456+thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data,
457+ const struct thermal_zone_of_device_ops *ops)
388458 {
389459 struct device_node *np, *child, *sensor_np;
390460 struct thermal_zone_device *tzd = ERR_PTR(-ENODEV);
@@ -426,9 +496,7 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id, · 35 unmodified lines
426496
427497 if (sensor_specs.np == sensor_np && id == sensor_id) {
428498 tzd = thermal_zone_of_add_sensor(child, sensor_np,
429− data,
430− get_temp,
431− get_trend);
499+ data, ops);
432500 of_node_put(sensor_specs.np);
433501 of_node_put(child);
434502 goto exit;
@@ -475,9 +543,9 @@ void thermal_zone_of_sensor_unregister(struct device *dev, · 40 unmodified lines
475543 mutex_lock(&tzd->lock);
476544 tzd->ops->get_temp = NULL;
477545 tzd->ops->get_trend = NULL;
546+ tzd->ops->set_emul_temp = NULL;
478547
479− tz->get_temp = NULL;
480− tz->get_trend = NULL;
548+ tz->ops = NULL;
481549 tz->sensor_data = NULL;
482550 mutex_unlock(&tzd->lock);
483551 }
@@ -501,7 +569,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_unregister); · 17 unmodified lines
501569 */
502570 static int thermal_of_populate_bind_params(struct device_node *np,
503571 struct __thermal_bind_params *__tbp,
504− struct __thermal_trip *trips,
572+ struct thermal_trip *trips,
505573 int ntrips)
506574 {
507575 struct of_phandle_args cooling_spec;
@@ -604,7 +672,7 @@ static int thermal_of_get_trip_type(struct device_node *np, · 96 unmodified lines
604672 * Return: 0 on success, proper error code otherwise
605673 */
606674 static int thermal_of_populate_trip(struct device_node *np,
607− struct __thermal_trip *trip)
675+ struct thermal_trip *trip)
608676 {
609677 int prop;
610678 int ret;
drivers/thermal/rockchip_thermal.c+693−0
@@ -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+ */
31+enum 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+ */
41+enum 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+ */
50+enum sensor_id {
51+ SENSOR_CPU = 1,
52+ SENSOR_GPU,
53+};
54+
55+struct 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+
72+struct 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+
80+struct 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+
126+struct tsadc_table {
127+ unsigned long code;
128+ long temp;
129+};
130+
131+static 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+
170+static 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+
194+static 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+ */
230+static 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+
249+static 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+
257+static 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+
270+static 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+
284+static 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+
296+static 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+
313+static 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+
326+static 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+};
333+MODULE_DEVICE_TABLE(of, of_rockchip_thermal_match);
334+
335+static void
336+rockchip_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+
344+static 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+
359+static 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+
373+static const struct thermal_zone_of_device_ops rockchip_of_thermal_ops = {
374+ .get_temp = rockchip_thermal_get_temp,
375+};
376+
377+static 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+
434+static int
435+rockchip_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+ */
463+static 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+
470+static 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+
589+err_unregister_gpu_sensor:
590+ thermal_zone_of_sensor_unregister(&pdev->dev, thermal->sensors[1].tzd);
591+err_unregister_cpu_sensor:
592+ thermal_zone_of_sensor_unregister(&pdev->dev, thermal->sensors[0].tzd);
593+err_disable_pclk:
594+ clk_disable_unprepare(thermal->pclk);
595+err_disable_clk:
596+ clk_disable_unprepare(thermal->clk);
597+
598+ return error;
599+}
600+
601+static 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+
621+static 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+
638+static 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+
674+static SIMPLE_DEV_PM_OPS(rockchip_thermal_pm_ops,
675+ rockchip_thermal_suspend, rockchip_thermal_resume);
676+
677+static 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+
688+module_platform_driver(rockchip_thermal_driver);
689+
690+MODULE_DESCRIPTION("ROCKCHIP THERMAL Driver");
691+MODULE_AUTHOR("Rockchip, Inc.");
692+MODULE_LICENSE("GPL v2");
693+MODULE_ALIAS("platform:rockchip-thermal");
drivers/thermal/samsung/exynos_thermal_common.h+0−1
@@ -27,7 +27,6 @@ · 26 unmodified lines
2727 #define SENSOR_NAME_LEN 16
2828 #define MAX_TRIP_COUNT 8
2929 #define MAX_COOLING_DEVICE 4
30−#define MAX_TRIMINFO_CTRL_REG 2
3130
3231 #define ACTIVE_INTERVAL 500
3332 #define IDLE_INTERVAL 10000
drivers/thermal/samsung/exynos_tmu.c+468−224
@@ -33,7 +33,87 @@ · 32 unmodified lines
3333
3434 #include "exynos_thermal_common.h"
3535 #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
37117
38118 /**
39119 * struct exynos_tmu_data : A structure to hold the private data of the TMU
@@ -52,6 +132,11 @@ · 12 unmodified lines
52132 * @temp_error2: fused value of the second point trim.
53133 * @regulator: pointer to the TMU regulator structure.
54134 * @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
55140 */
56141 struct exynos_tmu_data {
57142 int id;
@@ -66,6 +151,12 @@ struct exynos_tmu_data { · 8 unmodified lines
66151 u8 temp_error1, temp_error2;
67152 struct regulator *regulator;
68153 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);
69160 };
70161
71162 /*
@@ -122,83 +213,10 @@ static int code_to_temp(struct exynos_tmu_data *data, u8 temp_code) · 50 unmodified lines
122213 return temp;
123214 }
124215
125−static void exynos_tmu_clear_irqs(struct exynos_tmu_data *data)
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−
142−static int exynos_tmu_initialize(struct platform_device *pdev)
216+static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info)
143217 {
144− struct exynos_tmu_data *data = platform_get_drvdata(pdev);
145218 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);
155219
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− }
202220 data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
203221 data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) &
204222 EXYNOS_TMU_TEMP_MASK);
@@ -212,69 +230,37 @@ static int exynos_tmu_initialize(struct platform_device *pdev) · 7 unmodified lines
212230 data->temp_error2 =
213231 (pdata->efuse_value >> EXYNOS_TRIMINFO_85_SHIFT) &
214232 EXYNOS_TMU_TEMP_MASK;
233+}
215234
216− rising_threshold = readl(data->base + reg->threshold_th0);
235+static 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;
217239
218− if (data->soc == SOC_ARCH_EXYNOS4210) {
219− /* Write temperature code for threshold */
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));
240+ for (i = 0; i < pdata->non_hw_trigger_levels; i++) {
241+ u8 temp = pdata->trigger_levels[i];
226242
227− exynos_tmu_clear_irqs(data);
228− } else {
229− /* Write temperature code for rising and falling threshold */
230− for (i = 0; i < pdata->non_hw_trigger_levels; 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− }
243+ if (falling)
244+ temp -= pdata->threshold_falling;
245+ else
246+ threshold &= ~(0xff << 8 * i);
242247
243− writel(rising_threshold,
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− }
248+ threshold |= temp_to_code(data, temp) << 8 * i;
273249 }
274− /*Clear the PMIN in the common TMU register*/
275− if (reg->tmu_pmin && !data->id)
276− writel(0, data->base_second + reg->tmu_pmin);
277−out:
250+
251+ return threshold;
252+}
253+
254+static 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);
278264 clk_disable(data->clk);
279265 mutex_unlock(&data->lock);
280266 if (!IS_ERR(data->clk_sec))
@@ -283,20 +269,13 @@ out: · 2 unmodified lines
283269 return ret;
284270 }
285271
286−static void exynos_tmu_control(struct platform_device *pdev, bool on)
272+static u32 get_con_reg(struct exynos_tmu_data *data, u32 con)
287273 {
288− struct exynos_tmu_data *data = platform_get_drvdata(pdev);
289274 struct exynos_tmu_platform_data *pdata = data->pdata;
290− const struct exynos_tmu_registers *reg = pdata->registers;
291− unsigned int con, interrupt_en;
292275
293− mutex_lock(&data->lock);
294− clk_enable(data->clk);
295−
296− con = readl(data->base + reg->tmu_ctrl);
297−
298− if (pdata->test_mux)
299− con |= (pdata->test_mux << reg->test_mux_addr_shift);
276+ if (data->soc == SOC_ARCH_EXYNOS4412 ||
277+ data->soc == SOC_ARCH_EXYNOS3250)
278+ con |= (EXYNOS4412_MUX_ADDR_VALUE << EXYNOS4412_MUX_ADDR_SHIFT);
300279
301280 con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK << EXYNOS_TMU_REF_VOLTAGE_SHIFT);
302281 con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
@@ -305,95 +284,287 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on) · 2 unmodified lines
305284 con |= (pdata->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT);
306285
307286 if (pdata->noise_cancel_mode) {
308− con &= ~(reg->therm_trip_mode_mask <<
309− reg->therm_trip_mode_shift);
310− con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
287+ con &= ~(EXYNOS_TMU_TRIP_MODE_MASK << EXYNOS_TMU_TRIP_MODE_SHIFT);
288+ con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);
311289 }
312290
313− if (on) {
314− con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
315− interrupt_en =
316− pdata->trigger_enable[3] << reg->inten_rise3_shift |
317− pdata->trigger_enable[2] << reg->inten_rise2_shift |
318− pdata->trigger_enable[1] << reg->inten_rise1_shift |
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);
291+ return con;
292+}
293+
294+static void exynos_tmu_control(struct platform_device *pdev, bool on)
295+{
296+ struct exynos_tmu_data *data = platform_get_drvdata(pdev);
329297
298+ mutex_lock(&data->lock);
299+ clk_enable(data->clk);
300+ data->tmu_control(pdev, on);
330301 clk_disable(data->clk);
331302 mutex_unlock(&data->lock);
332303 }
333304
334−static int exynos_tmu_read(struct exynos_tmu_data *data)
305+static int exynos4210_tmu_initialize(struct platform_device *pdev)
335306 {
307+ struct exynos_tmu_data *data = platform_get_drvdata(pdev);
336308 struct exynos_tmu_platform_data *pdata = data->pdata;
337− const struct exynos_tmu_registers *reg = pdata->registers;
338− u8 temp_code;
339− int temp;
309+ unsigned int status;
310+ int ret = 0, threshold_code, i;
340311
341− mutex_lock(&data->lock);
342− clk_enable(data->clk);
312+ status = readb(data->base + EXYNOS_TMU_REG_STATUS);
313+ if (!status) {
314+ ret = -EBUSY;
315+ goto out;
316+ }
343317
344− temp_code = readb(data->base + reg->tmu_cur_temp);
318+ sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO));
345319
346− if (data->soc == SOC_ARCH_EXYNOS4210)
347− /* temp_code should range between 75 and 175 */
348− if (temp_code < 75 || temp_code > 175) {
349− temp = -ENODATA;
350− goto out;
320+ /* Write temperature code for threshold */
321+ threshold_code = temp_to_code(data, pdata->threshold);
322+ writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
323+
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);
329+out:
330+ return ret;
331+}
332+
333+static 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);
351353 }
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+ }
352358
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+ }
354387 out:
355− clk_disable(data->clk);
356− mutex_unlock(&data->lock);
388+ return ret;
389+}
357390
358− return temp;
391+static 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;
359440 }
360441
361−#ifdef CONFIG_THERMAL_EMULATION
362−static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
442+static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
363443 {
364− struct exynos_tmu_data *data = drv_data;
444+ struct exynos_tmu_data *data = platform_get_drvdata(pdev);
365445 struct exynos_tmu_platform_data *pdata = data->pdata;
366− const struct exynos_tmu_registers *reg = pdata->registers;
367− unsigned int val;
368− int ret = -EINVAL;
446+ unsigned int con, interrupt_en;
369447
370− if (!TMU_SUPPORTS(pdata, EMULATION))
371− goto out;
448+ con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
372449
373− if (temp && temp < MCELSIUS)
374− goto out;
450+ if (on) {
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+
468+static 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+
492+static int exynos_tmu_read(struct exynos_tmu_data *data)
493+{
494+ int ret;
375495
376496 mutex_lock(&data->lock);
377497 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);
378503
379− val = readl(data->base + reg->emul_con);
504+ return ret;
505+}
380506
507+#ifdef CONFIG_THERMAL_EMULATION
508+static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val,
509+ unsigned long temp)
510+{
381511 if (temp) {
382512 temp /= MCELSIUS;
383513
384− if (TMU_SUPPORTS(pdata, EMUL_TIME)) {
385− val &= ~(EXYNOS_EMUL_TIME_MASK << reg->emul_time_shift);
386− val |= (EXYNOS_EMUL_TIME << reg->emul_time_shift);
514+ if (data->soc != SOC_ARCH_EXYNOS5440) {
515+ val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT);
516+ val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT);
387517 }
388− val &= ~(EXYNOS_EMUL_DATA_MASK << reg->emul_temp_shift);
389− val |= (temp_to_code(data, temp) << reg->emul_temp_shift) |
518+ val &= ~(EXYNOS_EMUL_DATA_MASK << EXYNOS_EMUL_DATA_SHIFT);
519+ val |= (temp_to_code(data, temp) << EXYNOS_EMUL_DATA_SHIFT) |
390520 EXYNOS_EMUL_ENABLE;
391521 } else {
392522 val &= ~EXYNOS_EMUL_ENABLE;
393523 }
394524
395− writel(val, data->base + reg->emul_con);
525+ return val;
526+}
527+
528+static 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+
544+static 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+
554+static 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;
396561
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);
397568 clk_disable(data->clk);
398569 mutex_unlock(&data->lock);
399570 return 0;
@@ -401,23 +572,41 @@ out: · 1 unmodified line
401572 return ret;
402573 }
403574 #else
575+#define exynos4412_tmu_set_emulation NULL
576+#define exynos5440_tmu_set_emulation NULL
404577 static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
405578 { return -EINVAL; }
406579 #endif/*CONFIG_THERMAL_EMULATION*/
407580
581+static 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+
589+static int exynos4412_tmu_read(struct exynos_tmu_data *data)
590+{
591+ return readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
592+}
593+
594+static int exynos5440_tmu_read(struct exynos_tmu_data *data)
595+{
596+ return readb(data->base + EXYNOS5440_TMU_S0_7_TEMP);
597+}
598+
408599 static void exynos_tmu_work(struct work_struct *work)
409600 {
410601 struct exynos_tmu_data *data = container_of(work,
411602 struct exynos_tmu_data, irq_work);
412− struct exynos_tmu_platform_data *pdata = data->pdata;
413− const struct exynos_tmu_registers *reg = pdata->registers;
414603 unsigned int val_type;
415604
416605 if (!IS_ERR(data->clk_sec))
417606 clk_enable(data->clk_sec);
418607 /* Find which sensor generated this interrupt */
419− if (reg->tmu_irqstatus) {
420− val_type = readl(data->base_second + reg->tmu_irqstatus);
608+ if (data->soc == SOC_ARCH_EXYNOS5440) {
609+ val_type = readl(data->base_second + EXYNOS5440_TMU_IRQ_STATUS);
421610 if (!((val_type >> data->id) & 0x1))
422611 goto out;
423612 }
@@ -429,7 +618,7 @@ static void exynos_tmu_work(struct work_struct *work) · 5 unmodified lines
429618 clk_enable(data->clk);
430619
431620 /* TODO: take action based on particular interrupt */
432− exynos_tmu_clear_irqs(data);
621+ data->tmu_clear_irqs(data);
433622
434623 clk_disable(data->clk);
435624 mutex_unlock(&data->lock);
@@ -437,6 +626,40 @@ out: · 1 unmodified line
437626 enable_irq(data->irq);
438627 }
439628
629+static 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+
654+static 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+
440663 static irqreturn_t exynos_tmu_irq(int irq, void *id)
441664 {
442665 struct exynos_tmu_data *data = id;
@@ -450,35 +673,35 @@ static irqreturn_t exynos_tmu_irq(int irq, void *id) · 7 unmodified lines
450673 static const struct of_device_id exynos_tmu_match[] = {
451674 {
452675 .compatible = "samsung,exynos3250-tmu",
453− .data = (void *)EXYNOS3250_TMU_DRV_DATA,
676+ .data = &exynos3250_default_tmu_data,
454677 },
455678 {
456679 .compatible = "samsung,exynos4210-tmu",
457− .data = (void *)EXYNOS4210_TMU_DRV_DATA,
680+ .data = &exynos4210_default_tmu_data,
458681 },
459682 {
460683 .compatible = "samsung,exynos4412-tmu",
461− .data = (void *)EXYNOS4412_TMU_DRV_DATA,
684+ .data = &exynos4412_default_tmu_data,
462685 },
463686 {
464687 .compatible = "samsung,exynos5250-tmu",
465− .data = (void *)EXYNOS5250_TMU_DRV_DATA,
688+ .data = &exynos5250_default_tmu_data,
466689 },
467690 {
468691 .compatible = "samsung,exynos5260-tmu",
469− .data = (void *)EXYNOS5260_TMU_DRV_DATA,
692+ .data = &exynos5260_default_tmu_data,
470693 },
471694 {
472695 .compatible = "samsung,exynos5420-tmu",
473− .data = (void *)EXYNOS5420_TMU_DRV_DATA,
696+ .data = &exynos5420_default_tmu_data,
474697 },
475698 {
476699 .compatible = "samsung,exynos5420-tmu-ext-triminfo",
477− .data = (void *)EXYNOS5420_TMU_DRV_DATA,
700+ .data = &exynos5420_default_tmu_data,
478701 },
479702 {
480703 .compatible = "samsung,exynos5440-tmu",
481− .data = (void *)EXYNOS5440_TMU_DRV_DATA,
704+ .data = &exynos5440_default_tmu_data,
482705 },
483706 {},
484707 };
@@ -553,12 +776,47 @@ static int exynos_map_dt_data(struct platform_device *pdev) · 68 unmodified lines
553776 dev_err(&pdev->dev, "No platform init data supplied.\n");
554777 return -ENODEV;
555778 }
779+
556780 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+
557814 /*
558815 * Check if the TMU shares some registers and then try to map the
559816 * memory of common registers.
560817 */
561− if (!TMU_SUPPORTS(pdata, ADDRESS_MULTIPLE))
818+ if (data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO &&
819+ data->soc != SOC_ARCH_EXYNOS5440)
562820 return 0;
563821
564822 if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
@@ -625,20 +883,6 @@ static int exynos_tmu_probe(struct platform_device *pdev) · 60 unmodified lines
625883 goto err_clk_sec;
626884 }
627885
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−
642886 ret = exynos_tmu_initialize(pdev);
643887 if (ret) {
644888 dev_err(&pdev->dev, "Failed to initialize TMU\n");
drivers/thermal/samsung/exynos_tmu.h+9−114
@@ -40,114 +40,11 @@ enum soc_type { · 39 unmodified lines
4040 SOC_ARCH_EXYNOS4412,
4141 SOC_ARCH_EXYNOS5250,
4242 SOC_ARCH_EXYNOS5260,
43+ SOC_ARCH_EXYNOS5420,
4344 SOC_ARCH_EXYNOS5420_TRIMINFO,
4445 SOC_ARCH_EXYNOS5440,
4546 };
4647
47−/**
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− */
109−struct 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−
15148 /**
15249 * struct exynos_tmu_platform_data
15350 * @threshold: basic temperature for generating interrupt
@@ -192,16 +89,10 @@ struct exynos_tmu_registers { · 38 unmodified lines
19289 * @first_point_trim: temp value of the first point trimming
19390 * @second_point_trim: temp value of the second point trimming
19491 * @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
19792 * @cal_type: calibration type for temperature
19893 * @freq_clip_table: Table representing frequency reduction percentage.
19994 * @freq_tab_count: Count of the above table as frequency reduction may
20095 * 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
20596 *
20697 * This structure is required for configuration of exynos_tmu driver.
20798 */
@@ -223,15 +114,11 @@ struct exynos_tmu_platform_data { · 15 unmodified lines
223114 u8 first_point_trim;
224115 u8 second_point_trim;
225116 u8 default_temp_offset;
226− u8 test_mux;
227− u8 triminfo_reload[MAX_TRIMINFO_CTRL_REG];
228117
229118 enum calibration_type cal_type;
230119 enum soc_type type;
231120 struct freq_clip_table freq_tab[4];
232121 unsigned int freq_tab_count;
233− const struct exynos_tmu_registers *registers;
234− unsigned int features;
235122 };
236123
237124 /**
@@ -246,4 +133,12 @@ struct exynos_tmu_init_data { · 8 unmodified lines
246133 struct exynos_tmu_platform_data tmu_data[];
247134 };
248135
136+extern struct exynos_tmu_init_data const exynos3250_default_tmu_data;
137+extern struct exynos_tmu_init_data const exynos4210_default_tmu_data;
138+extern struct exynos_tmu_init_data const exynos4412_default_tmu_data;
139+extern struct exynos_tmu_init_data const exynos5250_default_tmu_data;
140+extern struct exynos_tmu_init_data const exynos5260_default_tmu_data;
141+extern struct exynos_tmu_init_data const exynos5420_default_tmu_data;
142+extern struct exynos_tmu_init_data const exynos5440_default_tmu_data;
143+
249144 #endif /* _EXYNOS_TMU_H */
drivers/thermal/samsung/exynos_tmu_data.c+8−231
@@ -22,24 +22,6 @@ · 21 unmodified lines
2222
2323 #include "exynos_thermal_common.h"
2424 #include "exynos_tmu.h"
25−#include "exynos_tmu_data.h"
26−
27−#if defined(CONFIG_CPU_EXYNOS4210)
28−static 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−};
4325
4426 struct exynos_tmu_init_data const exynos4210_default_tmu_data = {
4527 .tmu_data = {
@@ -75,40 +57,10 @@ struct exynos_tmu_init_data const exynos4210_default_tmu_data = { · 29 unmodified lines
7557 },
7658 .freq_tab_count = 2,
7759 .type = SOC_ARCH_EXYNOS4210,
78− .registers = &exynos4210_tmu_registers,
79− .features = TMU_SUPPORT_READY_STATUS,
8060 },
8161 },
8262 .tmu_count = 1,
8363 };
84−#endif
85−
86−#if defined(CONFIG_SOC_EXYNOS3250)
87−static 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−};
11264
11365 #define EXYNOS3250_TMU_DATA \
11466 .threshold_falling = 10, \
@@ -144,54 +96,17 @@ static const struct exynos_tmu_registers exynos3250_tmu_registers = { · 29 unmodified lines
14496 .freq_clip_max = 400 * 1000, \
14597 .temp_level = 95, \
14698 }, \
147− .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
99+ .freq_tab_count = 2
155100
156−#if defined(CONFIG_SOC_EXYNOS3250)
157101 struct exynos_tmu_init_data const exynos3250_default_tmu_data = {
158102 .tmu_data = {
159103 {
160104 EXYNOS3250_TMU_DATA,
161105 .type = SOC_ARCH_EXYNOS3250,
162− .test_mux = EXYNOS4412_MUX_ADDR_VALUE,
163106 },
164107 },
165108 .tmu_count = 1,
166109 };
167−#endif
168−
169−#if defined(CONFIG_SOC_EXYNOS4412) || defined(CONFIG_SOC_EXYNOS5250)
170−static 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−};
195110
196111 #define EXYNOS4412_TMU_DATA \
197112 .threshold_falling = 10, \
@@ -227,28 +142,18 @@ static const struct exynos_tmu_registers exynos4412_tmu_registers = { · 29 unmodified lines
227142 .freq_clip_max = 400 * 1000, \
228143 .temp_level = 95, \
229144 }, \
230− .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
145+ .freq_tab_count = 2
237146
238−#if defined(CONFIG_SOC_EXYNOS4412)
239147 struct exynos_tmu_init_data const exynos4412_default_tmu_data = {
240148 .tmu_data = {
241149 {
242150 EXYNOS4412_TMU_DATA,
243151 .type = SOC_ARCH_EXYNOS4412,
244− .test_mux = EXYNOS4412_MUX_ADDR_VALUE,
245152 },
246153 },
247154 .tmu_count = 1,
248155 };
249−#endif
250156
251−#if defined(CONFIG_SOC_EXYNOS5250)
252157 struct exynos_tmu_init_data const exynos5250_default_tmu_data = {
253158 .tmu_data = {
254159 {
@@ -258,31 +163,6 @@ struct exynos_tmu_init_data const exynos5250_default_tmu_data = { · 3 unmodified lines
258163 },
259164 .tmu_count = 1,
260165 };
261−#endif
262−
263−#if defined(CONFIG_SOC_EXYNOS5260)
264−static 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−};
286166
287167 #define __EXYNOS5260_TMU_DATA \
288168 .threshold_falling = 10, \
@@ -319,13 +199,10 @@ static const struct exynos_tmu_registers exynos5260_tmu_registers = { · 30 unmodified lines
319199 .temp_level = 103, \
320200 }, \
321201 .freq_tab_count = 2, \
322− .registers = &exynos5260_tmu_registers, \
323202
324203 #define EXYNOS5260_TMU_DATA \
325204 __EXYNOS5260_TMU_DATA \
326− .type = SOC_ARCH_EXYNOS5260, \
327− .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP | \
328− TMU_SUPPORT_READY_STATUS | TMU_SUPPORT_EMUL_TIME)
205+ .type = SOC_ARCH_EXYNOS5260
329206
330207 struct exynos_tmu_init_data const exynos5260_default_tmu_data = {
331208 .tmu_data = {
@@ -337,82 +214,14 @@ struct exynos_tmu_init_data const exynos5260_default_tmu_data = { · 5 unmodified lines
337214 },
338215 .tmu_count = 5,
339216 };
340−#endif
341−
342−#if defined(CONFIG_SOC_EXYNOS5420)
343−static 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, \
403217
404218 #define EXYNOS5420_TMU_DATA \
405− __EXYNOS5420_TMU_DATA \
406− .type = SOC_ARCH_EXYNOS5250, \
407− .features = (TMU_SUPPORT_EMULATION | TMU_SUPPORT_FALLING_TRIP | \
408− TMU_SUPPORT_READY_STATUS | TMU_SUPPORT_EMUL_TIME)
219+ __EXYNOS5260_TMU_DATA \
220+ .type = SOC_ARCH_EXYNOS5420
409221
410222 #define EXYNOS5420_TMU_DATA_SHARED \
411− __EXYNOS5420_TMU_DATA \
412− .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)
223+ __EXYNOS5260_TMU_DATA \
224+ .type = SOC_ARCH_EXYNOS5420_TRIMINFO
416225
417226 struct exynos_tmu_init_data const exynos5420_default_tmu_data = {
418227 .tmu_data = {
@@ -424,34 +233,6 @@ struct exynos_tmu_init_data const exynos5420_default_tmu_data = { · 5 unmodified lines
424233 },
425234 .tmu_count = 5,
426235 };
427−#endif
428−
429−#if defined(CONFIG_SOC_EXYNOS5440)
430−static 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−};
455236
456237 #define EXYNOS5440_TMU_DATA \
457238 .trigger_levels[0] = 100, \
@@ -471,10 +252,7 @@ static const struct exynos_tmu_registers exynos5440_tmu_registers = { · 13 unmodified lines
471252 .first_point_trim = 25, \
472253 .second_point_trim = 70, \
473254 .default_temp_offset = 25, \
474− .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),
255+ .type = SOC_ARCH_EXYNOS5440
478256
479257 struct exynos_tmu_init_data const exynos5440_default_tmu_data = {
480258 .tmu_data = {
@@ -484,4 +262,3 @@ struct exynos_tmu_init_data const exynos5440_default_tmu_data = { · 3 unmodified lines
484262 },
485263 .tmu_count = 3,
486264 };
487−#endif
drivers/thermal/samsung/exynos_tmu_data.h+0−159
@@ -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)
111−extern 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)
118−extern 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)
125−extern 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)
132−extern 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)
139−extern 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)
146−extern 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)
153−extern 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*/
drivers/thermal/tegra_soctherm.c+476−0
@@ -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+
80+struct tegra_tsensor_configuration {
81+ u32 tall, tsample, tiddq_en, ten_count, pdiv, tsample_ate, pdiv_ate;
82+};
83+
84+struct 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+
91+struct tegra_thermctl_zone {
92+ void __iomem *reg;
93+ unsigned int shift;
94+};
95+
96+static 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+
106+static 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+
165+struct 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+
174+struct tsensor_shared_calibration {
175+ u32 base_cp, base_ft;
176+ u32 actual_temp_cp, actual_temp_ft;
177+};
178+
179+static 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+
205+static 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+
216+static int
217+calculate_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+
261+static 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+ */
296+static 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+
309+static 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+
320+static const struct thermal_zone_of_device_ops tegra_of_thermal_ops = {
321+ .get_temp = tegra_thermctl_get_temp,
322+};
323+
324+static const struct of_device_id tegra_soctherm_of_match[] = {
325+ { .compatible = "nvidia,tegra124-soctherm" },
326+ { },
327+};
328+MODULE_DEVICE_TABLE(of, tegra_soctherm_of_match);
329+
330+struct thermctl_zone_desc {
331+ unsigned int offset;
332+ unsigned int shift;
333+};
334+
335+static 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+
342+static 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+
436+unregister_tzs:
437+ while (i--)
438+ thermal_zone_of_sensor_unregister(&pdev->dev,
439+ tegra->thermctl_tzs[i]);
440+
441+disable_clocks:
442+ clk_disable_unprepare(tegra->clock_tsensor);
443+ clk_disable_unprepare(tegra->clock_soctherm);
444+
445+ return err;
446+}
447+
448+static 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+
464+static 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+};
472+module_platform_driver(tegra_soctherm_driver);
473+
474+MODULE_AUTHOR("Mikko Perttunen <mperttunen@nvidia.com>");
475+MODULE_DESCRIPTION("NVIDIA Tegra SOCTHERM thermal management driver");
476+MODULE_LICENSE("GPL v2");
drivers/thermal/thermal_core.c+5−3
@@ -368,7 +368,7 @@ static void handle_critical_trips(struct thermal_zone_device *tz, · 367 unmodified lines
368368 tz->ops->get_trip_temp(tz, trip, &trip_temp);
369369
370370 /* 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)
372372 return;
373373
374374 trace_thermal_zone_trip(tz, trip, trip_type);
@@ -757,6 +757,7 @@ policy_store(struct device *dev, struct device_attribute *attr, · 382 unmodified lines
757757 snprintf(name, sizeof(name), "%s", buf);
758758
759759 mutex_lock(&thermal_governor_lock);
760+ mutex_lock(&tz->lock);
760761
761762 gov = __find_governor(strim(name));
762763 if (!gov)
@@ -766,6 +767,7 @@ policy_store(struct device *dev, struct device_attribute *attr, · 3 unmodified lines
766767 ret = count;
767768
768769 exit:
770+ mutex_unlock(&tz->lock);
769771 mutex_unlock(&thermal_governor_lock);
770772 return ret;
771773 }
@@ -1835,10 +1837,10 @@ static int __init thermal_init(void) · 1063 unmodified lines
18351837
18361838 exit_netlink:
18371839 genetlink_exit();
1838−unregister_governors:
1839− thermal_unregister_governors();
18401840 unregister_class:
18411841 class_unregister(&thermal_class);
1842+unregister_governors:
1843+ thermal_unregister_governors();
18421844 error:
18431845 idr_destroy(&thermal_tz_idr);
18441846 idr_destroy(&thermal_cdev_idr);
drivers/thermal/thermal_core.h+18−0
@@ -89,9 +89,27 @@ static inline void thermal_gov_user_space_unregister(void) {} · 88 unmodified lines
8989 #ifdef CONFIG_THERMAL_OF
9090 int of_parse_thermal_zones(void);
9191 void of_thermal_destroy_zones(void);
92+int of_thermal_get_ntrips(struct thermal_zone_device *);
93+bool of_thermal_is_trip_valid(struct thermal_zone_device *, int);
94+const struct thermal_trip * const
95+of_thermal_get_trip_points(struct thermal_zone_device *);
9296 #else
9397 static inline int of_parse_thermal_zones(void) { return 0; }
9498 static inline void of_thermal_destroy_zones(void) { }
99+static inline int of_thermal_get_ntrips(struct thermal_zone_device *tz)
100+{
101+ return 0;
102+}
103+static inline bool of_thermal_is_trip_valid(struct thermal_zone_device *tz,
104+ int trip)
105+{
106+ return 0;
107+}
108+static inline const struct thermal_trip * const
109+of_thermal_get_trip_points(struct thermal_zone_device *tz)
110+{
111+ return NULL;
112+}
95113 #endif
96114
97115 #endif /* __THERMAL_CORE_H__ */
drivers/thermal/ti-soc-thermal/ti-thermal-common.c+6−2
@@ -286,6 +286,11 @@ static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal, · 285 unmodified lines
286286 return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp);
287287 }
288288
289+static 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+
289294 static struct thermal_zone_device_ops ti_thermal_ops = {
290295 .get_temp = ti_thermal_get_temp,
291296 .get_trend = ti_thermal_get_trend,
@@ -333,8 +338,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, · 41 unmodified lines
333338
334339 /* in case this is specified by DT */
335340 data->ti_thermal = thermal_zone_of_sensor_register(bgp->dev, id,
336− data, __ti_thermal_get_temp,
337− __ti_thermal_get_trend);
341+ data, &ti_of_thermal_ops);
338342 if (IS_ERR(data->ti_thermal)) {
339343 /* Create thermal zone */
340344 data->ti_thermal = thermal_zone_device_register(domain,
include/dt-bindings/thermal/tegra124-soctherm.h+13−0
@@ -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
include/linux/clock_cooling.h+65−0
@@ -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+ */
36+struct thermal_cooling_device *
37+clock_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+ */
43+void clock_cooling_unregister(struct thermal_cooling_device *cdev);
44+
45+unsigned long clock_cooling_get_level(struct thermal_cooling_device *cdev,
46+ unsigned long freq);
47+#else /* !CONFIG_CLOCK_THERMAL */
48+static inline struct thermal_cooling_device *
49+clock_cooling_register(struct device *dev, const char *clock_name)
50+{
51+ return NULL;
52+}
53+static inline
54+void clock_cooling_unregister(struct thermal_cooling_device *cdev)
55+{
56+}
57+static inline
58+unsigned 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__ */
include/linux/thermal.h+37−36
@@ -29,10 +29,10 @@ · 28 unmodified lines
2929 #include <linux/idr.h>
3030 #include <linux/device.h>
3131 #include <linux/workqueue.h>
32+#include <uapi/linux/thermal.h>
3233
3334 #define THERMAL_TRIPS_NONE -1
3435 #define THERMAL_MAX_TRIPS 12
35−#define THERMAL_NAME_LENGTH 20
3636
3737 /* invalid cooling state */
3838 #define THERMAL_CSTATE_INVALID -1UL
@@ -49,11 +49,6 @@ · 10 unmodified lines
4949 #define MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, off) (((t) / 100) + (off))
5050 #define MILLICELSIUS_TO_DECI_KELVIN(t) MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, 2732)
5151
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−
5752 /* Default Thermal Governor */
5853 #if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE)
5954 #define DEFAULT_THERMAL_GOVERNOR "step_wise"
@@ -86,30 +81,6 @@ enum thermal_trend { · 26 unmodified lines
8681 THERMAL_TREND_DROP_FULL, /* apply lowest cooling action */
8782 };
8883
89−/* Events supported by Thermal Netlink */
90−enum events {
91− THERMAL_AUX0,
92− THERMAL_AUX1,
93− THERMAL_CRITICAL,
94− THERMAL_DEV_FAULT,
95−};
96−
97−/* attributes of thermal_genl_family */
98−enum {
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 */
106−enum {
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−
11384 struct thermal_zone_device_ops {
11485 int (*bind) (struct thermal_zone_device *,
11586 struct thermal_cooling_device *);
@@ -289,19 +260,49 @@ struct thermal_genl_event { · 173 unmodified lines
289260 enum events event;
290261 };
291262
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+ */
274+struct 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+
288+struct 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+
292295 /* Function declarations */
293296 #ifdef CONFIG_THERMAL_OF
294297 struct thermal_zone_device *
295−thermal_zone_of_sensor_register(struct device *dev, int id,
296− void *data, int (*get_temp)(void *, long *),
297− int (*get_trend)(void *, long *));
298+thermal_zone_of_sensor_register(struct device *dev, int id, void *data,
299+ const struct thermal_zone_of_device_ops *ops);
298300 void thermal_zone_of_sensor_unregister(struct device *dev,
299301 struct thermal_zone_device *tz);
300302 #else
301303 static inline struct thermal_zone_device *
302−thermal_zone_of_sensor_register(struct device *dev, int id,
303− void *data, int (*get_temp)(void *, long *),
304− int (*get_trend)(void *, long *))
304+thermal_zone_of_sensor_register(struct device *dev, int id, void *data,
305+ const struct thermal_zone_of_device_ops *ops)
305306 {
306307 return NULL;
307308 }
include/uapi/linux/Kbuild+1−0
@@ -387,6 +387,7 @@ header-y += tcp.h · 386 unmodified lines
387387 header-y += tcp_metrics.h
388388 header-y += telephony.h
389389 header-y += termios.h
390+header-y += thermal.h
390391 header-y += time.h
391392 header-y += times.h
392393 header-y += timex.h
include/uapi/linux/thermal.h+35−0
@@ -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 */
12+enum events {
13+ THERMAL_AUX0,
14+ THERMAL_AUX1,
15+ THERMAL_CRITICAL,
16+ THERMAL_DEV_FAULT,
17+};
18+
19+/* attributes of thermal_genl_family */
20+enum {
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 */
28+enum {
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 */