summaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-4.4/0044-Added-hwmon-thermal-driver-for-reporting-core-temper.patch
blob: 0834763e2440d4e3945e319d6872539f204e447c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
From 9f251fdbaaf3bd895c2901413748679d68a0c644 Mon Sep 17 00:00:00 2001
From: popcornmix <popcornmix@gmail.com>
Date: Tue, 26 Mar 2013 19:24:24 +0000
Subject: [PATCH 044/232] Added hwmon/thermal driver for reporting core
 temperature. Thanks Dorian
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

BCM270x: Move thermal sensor to Device Tree

Add Device Tree support to bcm2835-thermal driver.
Add thermal sensor device to Device Tree.
Don't add platform device when booting in DT mode.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
---
 drivers/thermal/Kconfig           |   7 ++
 drivers/thermal/Makefile          |   1 +
 drivers/thermal/bcm2835-thermal.c | 141 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 149 insertions(+)
 create mode 100644 drivers/thermal/bcm2835-thermal.c

--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -285,6 +285,13 @@ config INTEL_POWERCLAMP
 	  enforce idle time which results in more package C-state residency. The
 	  user interface is exposed via generic thermal framework.
 
+config THERMAL_BCM2835
+	depends on RASPBERRYPI_FIRMWARE
+	tristate "BCM2835 Thermal Driver"
+	help
+	  This will enable temperature monitoring for the Broadcom BCM2835
+	  chip. If built as a module, it will be called 'bcm2835-thermal'.
+
 config X86_PKG_TEMP_THERMAL
 	tristate "X86 package temperature thermal driver"
 	depends on X86_THERMAL_VECTOR
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_ARMADA_THERMAL)	+= armada_t
 obj-$(CONFIG_IMX_THERMAL)	+= imx_thermal.o
 obj-$(CONFIG_DB8500_CPUFREQ_COOLING)	+= db8500_cpufreq_cooling.o
 obj-$(CONFIG_INTEL_POWERCLAMP)	+= intel_powerclamp.o
+obj-$(CONFIG_THERMAL_BCM2835)	+= bcm2835-thermal.o
 obj-$(CONFIG_X86_PKG_TEMP_THERMAL)	+= x86_pkg_temp_thermal.o
 obj-$(CONFIG_INTEL_SOC_DTS_IOSF_CORE)	+= intel_soc_dts_iosf.o
 obj-$(CONFIG_INTEL_SOC_DTS_THERMAL)	+= intel_soc_dts_thermal.o
--- /dev/null
+++ b/drivers/thermal/bcm2835-thermal.c
@@ -0,0 +1,141 @@
+/*****************************************************************************
+* Copyright 2011 Broadcom Corporation.  All rights reserved.
+*
+* Unless you and Broadcom execute a separate written software license
+* agreement governing use of this software, this software is licensed to you
+* under the terms of the GNU General Public License version 2, available at
+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL").
+*
+* Notwithstanding the above, under no circumstances may you combine this
+* software in any way with any other Broadcom software provided under a
+* license other than the GPL, without Broadcom's express prior written
+* consent.
+*****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/thermal.h>
+#include <soc/bcm2835/raspberrypi-firmware.h>
+
+static int bcm2835_thermal_get_property(struct thermal_zone_device *tz,
+					int *temp, u32 tag)
+{
+	struct rpi_firmware *fw = tz->devdata;
+	struct {
+		u32 id;
+		u32 val;
+	} packet;
+	int ret;
+
+	*temp = 0;
+	packet.id = 0;
+	ret = rpi_firmware_property(fw, tag, &packet, sizeof(packet));
+	if (ret) {
+		dev_err(&tz->device, "Failed to get temperature\n");
+		return ret;
+	}
+
+	*temp = packet.val;
+	dev_dbg(&tz->device, "%stemp=%d\n",
+		tag == RPI_FIRMWARE_GET_MAX_TEMPERATURE ? "max" : "", *temp);
+
+	return 0;
+}
+
+static int bcm2835_thermal_get_temp(struct thermal_zone_device *tz,
+				    int *temp)
+{
+	return bcm2835_thermal_get_property(tz, temp,
+					    RPI_FIRMWARE_GET_TEMPERATURE);
+}
+
+static int bcm2835_thermal_get_max_temp(struct thermal_zone_device *tz,
+					int trip, int *temp)
+{
+	/*
+	 * The maximum safe temperature of the SoC.
+	 * Overclock may be disabled above this temperature.
+	 */
+	return bcm2835_thermal_get_property(tz, temp,
+					    RPI_FIRMWARE_GET_MAX_TEMPERATURE);
+}
+
+static int bcm2835_thermal_get_trip_type(struct thermal_zone_device *tz,
+					 int trip, enum thermal_trip_type *type)
+{
+	*type = THERMAL_TRIP_HOT;
+
+	return 0;
+}
+
+static int bcm2835_thermal_get_mode(struct thermal_zone_device *tz,
+				    enum thermal_device_mode *mode)
+{
+	*mode = THERMAL_DEVICE_ENABLED;
+
+	return 0;
+}
+
+static struct thermal_zone_device_ops ops  = {
+	.get_temp = bcm2835_thermal_get_temp,
+	.get_trip_temp = bcm2835_thermal_get_max_temp,
+	.get_trip_type = bcm2835_thermal_get_trip_type,
+	.get_mode = bcm2835_thermal_get_mode,
+};
+
+static int bcm2835_thermal_probe(struct platform_device *pdev)
+{
+	struct device_node *fw_np;
+	struct rpi_firmware *fw;
+	struct thermal_zone_device *tz;
+
+	fw_np = of_parse_phandle(pdev->dev.of_node, "firmware", 0);
+/* Remove comment when booting without Device Tree is no longer supported
+	if (!fw_np) {
+		dev_err(&pdev->dev, "Missing firmware node\n");
+		return -ENOENT;
+	}
+*/
+	fw = rpi_firmware_get(fw_np);
+	if (!fw)
+		return -EPROBE_DEFER;
+
+	tz = thermal_zone_device_register("bcm2835_thermal", 1, 0, fw, &ops,
+					  NULL, 0, 0);
+	if (IS_ERR(tz)) {
+		dev_err(&pdev->dev, "Failed to register the thermal device\n");
+		return PTR_ERR(tz);
+	}
+
+	platform_set_drvdata(pdev, tz);
+
+	return 0;
+}
+
+static int bcm2835_thermal_remove(struct platform_device *pdev)
+{
+	thermal_zone_device_unregister(platform_get_drvdata(pdev));
+
+	return 0;
+}
+
+static const struct of_device_id bcm2835_thermal_of_match_table[] = {
+	{ .compatible = "brcm,bcm2835-thermal", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table);
+
+static struct platform_driver bcm2835_thermal_driver = {
+	.probe = bcm2835_thermal_probe,
+	.remove = bcm2835_thermal_remove,
+	.driver = {
+		.name = "bcm2835_thermal",
+		.of_match_table = bcm2835_thermal_of_match_table,
+	},
+};
+module_platform_driver(bcm2835_thermal_driver);
+
+MODULE_AUTHOR("Dorian Peake");
+MODULE_AUTHOR("Noralf Trønnes");
+MODULE_DESCRIPTION("Thermal driver for bcm2835 chip");
+MODULE_LICENSE("GPL");