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
|
From 0a5d1b571ba5bca9c6737572ea4c8b1ad896c3fc Mon Sep 17 00:00:00 2001
From: Anson Huang <Anson.Huang@nxp.com>
Date: Wed, 7 Aug 2019 13:24:26 +0800
Subject: [PATCH] thermal: qoriq: Add device cooling support
Register device cooling for first thermal zone manually, when
temperature exceeds passive trip, system wide cooling notification
will be triggered.
Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
---
drivers/thermal/qoriq_thermal.c | 80 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 79 insertions(+), 1 deletion(-)
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -3,6 +3,7 @@
// Copyright 2016 Freescale Semiconductor, Inc.
#include <linux/clk.h>
+#include <linux/device_cooling.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/err.h>
@@ -14,6 +15,7 @@
#include "thermal_core.h"
#define SITES_MAX 16
+#define TMU_TEMP_PASSIVE_COOL_DELTA 10000
/*
* QorIQ TMU Registers
@@ -69,6 +71,9 @@ struct qoriq_sensor {
struct thermal_zone_device *tzd;
struct qoriq_tmu_data *qdata;
int id;
+ int temp_passive;
+ int temp_critical;
+ struct thermal_cooling_device *cdev;
};
struct qoriq_tmu_data {
@@ -78,6 +83,12 @@ struct qoriq_tmu_data {
struct qoriq_sensor *sensor[SITES_MAX];
};
+enum tmu_trip {
+ TMU_TRIP_PASSIVE,
+ TMU_TRIP_CRITICAL,
+ TMU_TRIP_NUM,
+};
+
static void tmu_write(struct qoriq_tmu_data *p, u32 val, void __iomem *addr)
{
if (p->little_endian)
@@ -106,14 +117,51 @@ static int tmu_get_temp(void *p, int *te
return 0;
}
+static int tmu_get_trend(void *p, int trip, enum thermal_trend *trend)
+{
+ struct qoriq_sensor *qsensor = p;
+ int trip_temp;
+
+ if (!qsensor->tzd)
+ return 0;
+
+ trip_temp = (trip == TMU_TRIP_PASSIVE) ? qsensor->temp_passive :
+ qsensor->temp_critical;
+
+ if (qsensor->tzd->temperature >=
+ (trip_temp - TMU_TEMP_PASSIVE_COOL_DELTA))
+ *trend = THERMAL_TREND_RAISE_FULL;
+ else
+ *trend = THERMAL_TREND_DROP_FULL;
+
+ return 0;
+}
+
+static int tmu_set_trip_temp(void *p, int trip,
+ int temp)
+{
+ struct qoriq_sensor *qsensor = p;
+
+ if (trip == TMU_TRIP_CRITICAL)
+ qsensor->temp_critical = temp;
+
+ if (trip == TMU_TRIP_PASSIVE)
+ qsensor->temp_passive = temp;
+
+ return 0;
+}
+
static const struct thermal_zone_of_device_ops tmu_tz_ops = {
.get_temp = tmu_get_temp,
+ .get_trend = tmu_get_trend,
+ .set_trip_temp = tmu_set_trip_temp,
};
static int qoriq_tmu_register_tmu_zone(struct platform_device *pdev)
{
struct qoriq_tmu_data *qdata = platform_get_drvdata(pdev);
- int id, sites = 0;
+ const struct thermal_trip *trip;
+ int id, sites = 0, ret;
for (id = 0; id < SITES_MAX; id++) {
qdata->sensor[id] = devm_kzalloc(&pdev->dev,
@@ -132,6 +180,36 @@ static int qoriq_tmu_register_tmu_zone(s
return PTR_ERR(qdata->sensor[id]->tzd);
}
+ /* first thermal zone takes care of system-wide device cooling */
+ if (id == 0) {
+ qdata->sensor[id]->cdev = devfreq_cooling_register();
+ if (IS_ERR(qdata->sensor[id]->cdev)) {
+ ret = PTR_ERR(qdata->sensor[id]->cdev);
+ pr_err("failed to register devfreq cooling device: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = thermal_zone_bind_cooling_device(qdata->sensor[id]->tzd,
+ TMU_TRIP_PASSIVE,
+ qdata->sensor[id]->cdev,
+ THERMAL_NO_LIMIT,
+ THERMAL_NO_LIMIT,
+ THERMAL_WEIGHT_DEFAULT);
+ if (ret) {
+ pr_err("binding zone %s with cdev %s failed:%d\n",
+ qdata->sensor[id]->tzd->type,
+ qdata->sensor[id]->cdev->type,
+ ret);
+ devfreq_cooling_unregister(qdata->sensor[id]->cdev);
+ return ret;
+ }
+
+ trip = of_thermal_get_trip_points(qdata->sensor[id]->tzd);
+ qdata->sensor[id]->temp_passive = trip[0].temperature;
+ qdata->sensor[id]->temp_critical = trip[1].temperature;
+ }
+
sites |= 0x1 << (15 - id);
}
|